2016-12-30 9 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"]

Я пытался форматировать с помощью этого :

Но я получаю это

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

Если я использую словарь я не могу иметь дубликаты. Как я могу продолжить это?

+2

Мой * думаю *, что 'вар ShoppingList = [ "Брюки: 15,50", "Брюки: 15,50", "Jumper: 12,99", "Обувь: 50.00"]' –

+2

I будет группировать все эти данные внутри 'struct' или' class', вместо того, чтобы вы использовали словарь, тогда вы могли бы получить какое-то свойство размера ваших предметов. 'struct Grouping {var Key: String var values: [String]}' – Lamar

+0

Знаете ли вы, что '[Trousers: 15.50, Trousers: 15.50, Jumper: 12.99, Shoes: 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", "1x обувь: £ 50,0", "1x Jumper: £ 12,99"]

+0

Это довольно близко, если мы добавим let formattedShoppingList = counts.map {item, count in "\ (count) x \ (item.name): £ \ (item.price * Double (count)) "} – Christian

+0

Обратите внимание, что вы не должны использовать двоичный тип с плавающей запятой, например' Double' для представления денежных значений, вместо этого используйте ['Decimal'] (https://developer.apple.com/reference/foundation/decimal). Кроме того, простой цикл for-in был бы предпочтительнее, чем «уменьшить» производительность из-за того, что '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 
} 

с его помощью вы можете конвертировать список покупок, в список торговых пунктов, как это (примите во внимание, что отбрасывается элементы не могут трансформировать, можно проверить nil it Эмс, чтобы убедиться, что все могут быть преобразованы):

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

Как это решить его проблему?Исправьте меня, если я ошибаюсь, но это должно просто напечатать каждый элемент массива, который не дает ему предпочтительного форматирования. –

 Смежные вопросы

  • Нет связанных вопросов^_^