Вы можете достичь результатов за O(nlogn)
время, сначала создав Dictionary
, содержащее количество вхождений для каждого элемента (O(n)
), затем вызвав sorted
для Array
( Swift использует Introsort , который O(nlogn)
) и использует значения из ранее созданного Dictionary
для сортировки. Элементами вашего массива должны быть Comparable
, чтобы сортировка работала, и Hashable
, чтобы иметь возможность хранить их в Dictionary
, что обеспечивает O(1)
поиск элементов.
extension Array where Element: Comparable & Hashable {
func sortByNumberOfOccurences() -> [Element] {
let occurencesDict = self.reduce(into: [Element:Int](), { currentResult, element in
currentResult[element, default: 0] += 1
})
return self.sorted(by: { current, next in occurencesDict[current]! < occurencesDict[next]!})
}
}
[1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2].sortByNumberOfOccurences() // [1, 4, 3, 2, 2, 5, 5, 5, 6, 6, 6, 6]
Приведенное выше решение сохраняет порядок элементов, которые встречаются равное количество раз. Если вы действительно хотите отсортировать такие элементы на основе их сравниваемых значений (что и делает ваш пример выходных данных), вы можете изменить замыкание в sorted
, как показано ниже:
return self.sorted(by: {occurencesDict[$0]! <= occurencesDict[$1]! && $0 < $1})
Или даже короче, , сравнивая tuples
для сортировки :
return self.sorted(by: {(occurencesDict[$0]!,$0) < (occurencesDict[$1]!,$1)})
, который дает предоставленный вами образец выборки, [1, 3, 4, 2, 2, 5, 5, 5, 6, 6, 6, 6]