2015-09-15 4 views
0

спасибо за чтение моего сообщения.Сортировка массива на основе второго значения кортежа

У меня есть массив кортежей объявленных как таковые:

var myArray: [(item1: String?, item2: NSDate?)] = []

В конце моего цикла я хочу, чтобы отсортировать мой массив кортежей на основе каждого кортеж item2, тип которого NSDate?.

Основываясь на этом answer и this answer Я пробовал следующее, но получил эту ошибку от компилятора, "cannot invoke 'sort' with an argument list of type '((_,_) -> _)'.

Вот что я пробовал:

myArray.sort {$0.1.item2?.compare($1.1.item2?) == NSComparisonResult.OrderedDescending } 

P.S. println() отлично работает и печатает item1 и item2 как необязательный.

+4

Неправильная практика использования кортежей в структурах данных, вместо этого используйте массив или словарь. Из Apple Swift iBook: «Кортежи полезны для временных групп связанных значений. Они не подходят для создания сложных структур данных. ** Если ваша структура данных, скорее всего, сохранится за пределами временной области, моделируйте ее как класс или структуру, а не как кортеж. ** « Выдержка из: Apple Inc.« Язык быстрого программирования (Swift 2 Prerelease) . "IBooks. https://itun.es/us/k5SW7.l – zaph

ответ

1

Вы должны реализовать Comparable протокола NSDate

public func ==(lhs: NSDate, rhs: NSDate) -> Bool { 
    return lhs === rhs || lhs.compare(rhs) == .OrderedSame 
} 

public func <(lhs: NSDate, rhs: NSDate) -> Bool { 
    return lhs.compare(rhs) == .OrderedAscending 
} 

extension NSDate: Comparable { } 

После этого вы можете сортировать кортежи по дате:

myArray!.sort {$0.1 == $1.1 ? $0.1 > $1.1 : $0.1 > $1.1 } 
+0

Спасибо за ваш ответ. Я просто попробовал ваше решение, это не сработало. [здесь] (http://stackoverflow.com/questions/26577496/how-do-i-sort-a-swift-array-containing-instances-of-nsmanagedobject-subclass-by) Я не могу сравнивать 'NSDate' напрямую с '<'. Может быть, это что-то еще? – Sami

+0

отредактировал мое сообщение .. u должен реализовать Сопоставимый сначала NSDate .. –

+0

Да, это сработало спасибо! Однако @zaph упомянул, что я должен рассмотреть возможность переключения на массивы или словари, поэтому я, вероятно, в конечном итоге сделаю это, поэтому я придерживаюсь хорошей практики. Спасибо за быстрый ответ. – Sami

0

Альтернатива принятого решения:

let res = myArray.sort { (left, right) -> Bool in 
    return left.item2?.timeIntervalSinceReferenceDate < right.item2?.timeIntervalSinceReferenceDate 
} 
0

причина, по которой связанные решения не работали, состоит в том, что массив кортежей, определенный в вопросе c имеет дополнительные типы.

Проверка дополнительных параметров устраняет проблему, не добавляя новых операторов в NSDate.

Пример, с 3-мя датами и необязательных типов:

var myArray: [(item1: String?, item2: NSDate?)] = [] 
myArray = [("now", NSDate()), ("now+30s", NSDate().dateByAddingTimeInterval(NSTimeInterval(30))), ("now-30s", NSDate().dateByAddingTimeInterval(NSTimeInterval(-30)))] 

myArray.sortInPlace { (lhs, rhs) -> Bool in 
    if lhs.item2 != nil && rhs.item2 != nil { 
     return lhs.item2!.compare(rhs.item2!) == .OrderedAscending 
    } 
    return false // Return true if you want nil values first 
} 

тот же код, если типы не позволяют опциями:

var myArray: [(item1: String, item2: NSDate)] = [] 
myArray = [("now", NSDate()), ("now+30s", NSDate().dateByAddingTimeInterval(NSTimeInterval(30))), ("now-30s", NSDate().dateByAddingTimeInterval(NSTimeInterval(-30)))] 

myArray.sortInPlace { (lhs, rhs) -> Bool in 
    return lhs.item2.compare(rhs.item2) == .OrderedAscending 
} 

решение MirekE также работает хорошо, но вы не имеют контроля над тем, где заканчиваются значения nil (они будут в начале).

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