2015-02-17 6 views
0

У меня есть массив сделок формата:Swift - сортировка массива доллара значения

"$ 2,25 Пейте"

"$ 5 Пейте B"

"$ 10 Напиток C"

и т. Д.

и я хочу отсортировать их по цене в долларах.

deals.sort { 
     var first = $0.deal as String 
     var second = $1.deal as String 

     var myArr1 = first.componentsSeparatedByString(" ") 
     var myArr2 = second.componentsSeparatedByString(" ") 

     var formatter = NSNumberFormatter() 
     formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle 

     if let price1 = formatter.numberFromString(myArr1[0]) as NSNumber! { 
      if let price2 = formatter.numberFromString(myArr2[0]) as NSNumber!{ 
       return first < second 
      } 
     } 
     return false 
    } 

Это нормально работает для значений, таких как $ 4.25 и любой цифры. Если я попробую что-то вроде 10,25 долларов США, он не будет правильно сортироваться.

Вот площадка Я использую тест-код

import UIKit 


var deals: [(deal:String, bar:String)] = [] 

deals.append(deal: "$0.95" as String, bar: "bar" as String) 
deals.append(deal: "$2.95" as String, bar: "bar" as String) 
deals.append(deal: "$11.95" as String, bar: "bar" as String) 
deals.append(deal: "$3.95" as String, bar: "bar" as String) 


deals.sort { 
    var first = $0.deal as String 
    var second = $1.deal as String 

    var myArr1 = first.componentsSeparatedByString(" ") 
    var myArr2 = second.componentsSeparatedByString(" ") 

    var formatter = NSNumberFormatter() 
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle 

    if let price1 = formatter.numberFromString(myArr1[0]) as NSNumber! { 
     if let price2 = formatter.numberFromString(myArr2[0]) as NSNumber!{ 
      return first < second 
     } 
    } 
    return false 
} 

for deal in deals{ 
    print("\(deal.deal)\n") 
} 
+0

Да, я мог бы, но на данном этапе не имеет значения, как я получу номер, если сравнение неверно. Считаете ли вы, что изменить это, чтобы сравнить напрямую, это исправить? – leerob

+1

Я думаю, вы должны сохранить его как Двойной и отформатировать его как валюту при ее отображении. –

+0

В итоге я сделал что-то похожее на это. Моя сделка не содержала всего доллара, она также содержала некоторый текст. Поэтому мне нужно было хранить только сумму в долларах отдельно. Но спасибо за предложение! – leerob

ответ

1

Корень вашей проблемы состоит в том, что вы сортируете в алфавитном порядке, а не в цифрах. Численно, 4.25 сортировки до 10.25, потому что 4.25 < 10.25. По алфавиту, 10.99 приходит до 4.25, потому что код символа для 1 меньше, чем для 4. Чтобы устранить проблему, вам, очевидно, нужно как-то получить номер, соответствующий цене сделки.

Вы можете написать метод, который извлекает цену из записи и возвращает ее как число, которое вы можете затем правильно сравнить. Лучше хранить каждую сделку как словарь или другую структуру, чтобы цена уже выходила как отдельное значение.

+0

Это объяснение, в котором я нуждался. Я использовал совет Ромена и добавил «сумму ", который содержал число с плавающей запятой, поэтому сортировка была простым сравнением. Поэтому спасибо вам обоим! – leerob

2

EDIT: Я знаю, что вы уже приняли ответ, но FWIW, основываясь на свой вопрос редактирования, я обновил мой ответ ниже, чтобы показать вам, как изменить код вашей площадки, чтобы мое первоначальное предложение работало.

deals.sort{ 
    let myArr1 = $0.deal.componentsSeparatedByString(" ") 
    let myArr2 = $1.deal.componentsSeparatedByString(" ") 
    let formatter = NSNumberFormatter() 
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle 

    if let price1 = formatter.numberFromString(myArr1[0]) { 
     if let price2 = formatter.numberFromString(myArr2[0]) { 
      return price1.floatValue < price2.floatValue 
     } 
    } 
    return false 
} 

Другое предложение заключалось в том, что вы могли бы сделать еще проще, если бы вы имели Deal класс, со специфическим свойством, возвращающего значение с плавающей точкой сделки, как это:

var dealValue: Float { 
    get { 
     let myArr = self.deal.componentsSeparatedByString(" ") 
     let formatter = NSNumberFormatter() 
     formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle 
     if let price = formatter.numberFromString(myArr[0]) { 
      return price.floatValue 
     } else { 
      return 0 
     } 
    } 
} 

Тогда предыдущий код просто станет:

deals.sort { $0.dealValue < $1.dealValue } 
+0

Я просто попробовал свой код с некоторыми изменениями. Операторы let всегда возвращают null. Я отредактировал исходное сообщение с моим кодом. – leerob

+0

Я удалял $ и все еще использовал CurrencyStyle, который вызывал ошибку. Дурак я. Тем не менее, я не могу вернуть price1 leerob

+0

Это не работает для этого примера ... «$ 89» «$ 2.95 "" $ 9.95 "" $ 99.95 ":/ – leerob

0

Я думаю, вы должны сохранить его как Двойной и отформатировать его как валюту при ее отображении.

extension Double { 
    var currency:String { 
     let formatter = NSNumberFormatter() 
     formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle 
     return formatter.stringFromNumber(self)! 
    } 
} 
var deals: [(deal:Double, bar:String)] = [] 
deals.append(deal: 0.95 , bar: "bar") 
deals.append(deal: 2.95 , bar: "bar") 
deals.append(deal: 11.95, bar: "bar") 
deals.append(deal: 3.95, bar: "bar") 


deals.sort {$0.deal<$1.deal} 

for deal in deals{ 
    print("\(deal.deal.currency)\n") 
} 
Смежные вопросы