您正在寻找的是获取值的频率的方法.只要值是Hashable
这个函数将起作用:
它扩展了所有序列类型的地方Element
是Hashable
,这样的阵列Int
将起作用.
extension SequenceType where Generator.Element : Hashable { func frequencies() -> [Generator.Element:Int] { var results : [Generator.Element:Int] = [:] for element in self { results[element] = (results[element] ?? 0) + 1 } return results } }
然后你可以这样做:
let alpha = [2,8,2,6,1,8,2,6,6] let sorted = alpha.frequencies().sort { if $0.1 > $1.1 { // if the frequency is higher, return true return true } else if $0.1 == $1.1 { // if the frequency is equal return $0.0 > $1.0 // return value is higher } else { return false // else return false } }
更好的是,您现在可以为序列类型创建另一个扩展.现在他们需要遵守Comparable
以及Hashable
extension SequenceType where Generator.Element : protocol{ func sortByFrequency() -> [Generator.Element] { // the same sort function as before let sorted = self.frequencies().sort { if $0.1 > $1.1 { return true } else if $0.1 == $1.1 { return $0.0 > $1.0 } else { return false } } // this is to convert back from the dictionary to an array var sortedValues : [Generator.Element] = [] sorted.forEach { // for each time the value was found for _ in 0..<$0.1 { sortedValues.append($0.0) // append } } return sortedValues } }
你对这一切的最终用法将如下所示:
let sorted = alpha.sortByFrequency() // [6, 6, 6, 2, 2, 2, 8, 8, 1]
超级干净:)
如果您更喜欢靠近sort
自身的功能,您也可以使用:
extension SequenceType where Generator.Element : Hashable { func sortedFrequency(@noescape isOrderedBefore: ((Self.Generator.Element,Int), (Self.Generator.Element,Int)) -> Bool) -> [Generator.Element] { let sorted = self.frequencies().sort { return isOrderedBefore($0,$1) // this uses the closure to sort } var sortedValues : [Generator.Element] = [] sorted.forEach { for _ in 0..<$0.1 { sortedValues.append($0.0) } } return sortedValues } }
上面的扩展在内部将数组转换为频率字典,并要求您输入一个closure
返回a 的频率字典Bool
.然后,您可以根据需要应用不同的排序.
因为您将具有排序逻辑的闭包传递给此函数Elements
,所以SequenceType
不再需要进行比较.
所有速记的备忘单:
$0 // first element $1 // second element $0.0 // value of first element $0.1 // frequency of first element
排序:
let sortedB = alpha.sortedFrequency { if $0.1 > $1.1 { return true } else if $0.1 == $1.1 { return $0.0 > $1.0 } else { return false } } // [6, 6, 6, 2, 2, 2, 8, 8, 1]