arrays - 计算数组中的数字并按 swift 计数对它们进行排序

标签 arrays swift

有没有一种简单的方法可以根据数字的个数对数组进行排序?如果一个数字具有相同的计数,则将最大的数字放在第一位。

[2,8,2,6,1,8,2,6,6] 
to
[6,6,6,2,2,2,8,8,1]

最佳答案

您正在寻找一种获取值频率的方法。 只要值是Hashable,这个函数就可以工作:

它扩展了 ElementHashable 的所有序列类型,因此 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<Hashable,Comparable> {
    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]

super 干净:)


如果你更喜欢一个更接近 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
    }
}

上面的扩展在内部将数组转换为频率字典,只要求您输入一个返回 Boolclosure。然后您可以根据需要应用不同的排序。

因为您将带有排序逻辑的闭包传递给此函数,所以 SequenceTypeElements 不再需要具有可比性。

所有速记的备忘单:

$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]

关于arrays - 计算数组中的数字并按 swift 计数对它们进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34614782/

相关文章:

ios - UITableViewCell 的内容 View 的 masksToBounds 属性不起作用

ios - 如何通过扩展将类的方法与某些自定义方法混合

php - 如何以矩阵模式访问 MySQL 表中的值?

java - Java 从数组中删除元素

C - 动态数组处理建议

java - 如何将字节数组转换为 Int 数组

ios - 如何在IOS中将文本文件保存为变量

swift - AppDelegates 函数 "supportedInterfaceOrientationsFor"不会在 iPad 上被调用

php - 多维数组,去掉key和value匹配到另一个数组的数组

ios - timeInterval 变量不起作用