2016-12-30 3 views
1

Je dispose d'un tableau formaté comme ceci:Formatage un tableau comme une liste d'achats

["Trousers : 15.50", "Trousers : 15.50", "Jumper : 12.99", "Shoes: 50.00"]

Je voudrais formater comme ceci:

["2x Trousers : 31.00", "1x Jumper : 12.99", "1x Shoes: 50.00"]

J'essayé de formater en utilisant cette :

var counts: [String:Int] = [:] 
var shoppingList = ["Trousers : 15.50", "Trousers : 15.50", "Jumper : 12.99", "Shoes: 50.00"] 
var formattedShoppingList = [String]() 

    for item in shoppingList { 
     counts[item] = (counts[item] ?? 0) + 1 
    } 


    for (key, value) in counts { 

     let display:String = String(value) + "x " + key 
     formattedShoppingList.append(display) 

    } 

Mais je reçois ce

["2x Trousers : 15.50", "1x Jumper : 12.99", "1x Shoes: 50.00"]

Si j'utilise un dictionnaire, je ne peux pas avoir des doublons. Comment dois-je procéder avec cela?

+2

Ma * estimation * est que 'var ShoppingList = [ "Pantalon: 15,50", "Pantalon: 15,50", "Jumper: 12.99", "Chaussures: 50.00"]' –

+2

I regrouperait toutes ces données dans un 'struct' ou' class', au lieu que vous utilisiez un dictionnaire, alors vous pourriez avoir une propriété obtenant la taille de vos éléments. 'struct Grouping {var Clé: String var values: [String]}' – Lamar

+0

Etes-vous conscient que '[Pantalons: 15.50, Pantalons: 15.50, Jumper: 12.99, Chaussures: 50.00]' n'est pas un tableau? – Alexander

Répondre

1

Je ferais une structure pour représenter les paires nom/prix d'article (et peut-être d'autres données dans le futur, comme la quantité en stock, par exemple).

struct Item: Hashable { 
    let name: String 
    let price: Double 

    public var hashValue: Int { return name.hashValue^price.hashValue } 

    public static func ==(lhs: Item, rhs: Item) -> Bool { 
     return lhs.name == rhs.name && rhs.price == rhs.price 
    } 
} 

let shoppingList = [ 
    Item(name: "Trousers", price: 15.50), 
    Item(name: "Trousers", price: 15.50), 
    Item(name: "Jumper", price: 12.99), 
    Item(name: "Shoes", price: 50), 
] 

let counts = shoppingList.reduce([Item: Int]()){counts, item in 
    var counts = counts 
    counts[item] = (counts[item] ?? 0) + 1 
    return counts 
} 

let formattedShoppingList = counts.map{ item, count in "\(count)x \(item.name): £\(item.price)" } 

print(formattedShoppingList) 

[ "2x Pantalon: £ 15,5", "1x Chaussures: £ 50.0", "1x Jumper: £ 12.99"]

+0

Ceci est assez proche si on ajoute let formattedShoppingList = counts.map {item, comptez dans "\ (count) x \ (item.name): £ \ (item.price * Double (count) }}} – Christian

+0

Notez que vous ne devez pas utiliser un type de virgule flottante binaire comme 'Double' pour représenter des valeurs monétaires - utilisez plutôt [' Decimal'] (https://developer.apple.com/reference/foundation/decimal). De plus, une simple boucle for-in serait préférable à une réduction des performances du fait que réduire réduirait inutilement une copie du dictionnaire cumulatif à chaque itération. – Hamish

+0

@Christian Bon point, corrigé. – Alexander

1

Vous pouvez utiliser cette structure, qui accepte vos cordes comme paramètre pour le constructeur:

struct ShoppingItem: Hashable { 
    let name: String 
    let price: NSDecimalNumber 

    //Expects a String in the form "ElementName : Price" 
    init?(description: String) { 
     let splitDescription = description.components(separatedBy: ":") 

     guard splitDescription.count == 2 else { return nil } 

     name = splitDescription[0].trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) 
     price = NSDecimalNumber(string: splitDescription[1]) 
    } 

    public var hashValue: Int { 
     return "\(name)\(price)".hashValue 
    } 
} 
func ==(lhs: ShoppingItem, rhs: ShoppingItem) -> Bool { 
    return lhs.hashValue == rhs.hashValue 
} 

Avec lui, vous pouvez convertir votre liste d'achats, à une liste d'articles commerciaux comme celui-ci (prendre en compte, que ce défausse éléments qu'il ne peut pas transformer, vous pouvez vérifier nul ems pour vous assurer que tous puissent être convertis):

var shoppingItems = shoppingList.flatMap(ShoppingItem.init(description:)) 

puis, vous faites tout ce que vous avez fait avant, multiplier seulement le prix à la fin:

var counts = [ShoppingItem: Int]() 
for item in shoppingItems { 
    counts[item] = (counts[item] ?? 0) + 1 
} 

for (key, value) in counts { 
    let multipliedPrice = key.price.multiplying(by: NSDecimalNumber(value: value)) 
    let display = "\(value)x \(key.name) : \(multipliedPrice)" 
    formattedShoppingList.append(display) 
} 
-1

Vous n'avez pas besoin struct ou classe pour une paire simple; utiliser un tableau de tuples:

var shoppingList = [("Trousers", 15.50), ("Trousers", 15.50), ("Jumper", 12.99), ("Shoes", 50.00)] 

    for (name, price) in shoppingList { 
     print(name, price) 
    } 
+1

Comment cela résout-il son problème?Corrigez-moi si je me trompe, mais cela devrait simplement imprimer chaque élément du tableau, ce qui ne lui donne pas son formatage préféré. –