2016-12-30 21 views
1

我有一個數組格式如下:格式就像一個購物清單的陣列

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

我想這樣來格式化:

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

我嘗試使用此格式:

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) 

    } 

但我得到這個

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

如果我使用一本字典,我不能有重複。我該如何着手解決這個問題?

+2

我*猜測*是'VAR shoppingList = [ 「褲子:15.50」, 「褲:15.50」, 「跳線:12.99」, 「鞋:50.00」]' –

+2

我將所有這些數據分組在一個'struct'或'class'中,而不是使用字典,那麼你可以使用一些屬性來獲得你的項目的大小。 '結構分組{var Key:String var values:[String]}' – Lamar

+0

你知道'[褲子:15.50,褲子:15.50,跳線:12.99,鞋子:50.00]'不是數組嗎? – Alexander

回答

1

我會做一個結構來表示項目名稱/價格對(以及未來的其他數據,比如庫存數量)。

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褲子:£15.5」, 「1個鞋:£50.0」, 「1個跳線:£12.99」]

+0

如果我們添加let formatterShoppingList = counts.map {item,count在「\(count)x \(item.name):£\(item.price * Double(count) )「} – Christian

+0

請注意,您不應該使用像Double這樣的二進制浮點類型來表示貨幣值 - 而應該使用['Decimal'](https://developer.apple.com/reference/foundation/decimal)」。還有一個簡單的for-in循環比'reduce'性能明顯更可取,因爲reduce會在每次迭代時不必要地複製累加字典。 – Hamish

+0

@Christian好點,固定。 – Alexander

1

你可以使用這個結構,它接受你的字符串作爲參數的構造函數:

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 
} 

有了它,你可以轉換你的購物清單,購物的物品像這樣的列表(考慮到,這個物品丟棄它不能改變,你可以檢查無它EMS,以確保所有可轉換):

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

,然後,你只是做你做了什麼之前,只有乘以價格底:

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

你並不需要一個結構或爲一對簡單的類;使用元組的數組:

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

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

這是如何解決他的問題?糾正我,如果我錯了,但這應該只是打印陣列的每個元素,這不會給他他喜歡的格式。 –