【问题标题】:Removing the smaller sets of values from an array of arrays in Swift从 Swift 中的数组数组中删除较小的值集
【发布时间】:2016-10-02 21:37:17
【问题描述】:

给定一个由包含整数的数组组成的数组。

[[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]

在 Swift 中,删除包含具有特定值的元素数量较少的数组并仅保留包含该值的较大数组的首选方法是什么。

上面输入的结果是

[[5], [7], [2, 2, 2], [3, 3]]

【问题讨论】:

  • 您必须更具体。你想让这个稳定(保持原来的顺序),重复的应该怎么做?我假设你只想要数量最多的数组。
  • 顺序无关紧要,我已经编辑了我的问题以使其更清楚。是的,只有数量最多的数组。

标签: arrays swift


【解决方案1】:

只是使用 forEach 的替代方法:

let arrays = [[2],  [2, 2], [5], [7], [2, 2, 2], [3, 3], [3]]
var largest: [Int: [Int]] = [:]

arrays.forEach({
    guard let first = $0.first else { return }
    largest[first] = [Int](count: max($0.count,largest[first]?.count ?? 0), repeatedValue: first)
})
Array(largest.values)  // [[5], [7], [2, 2, 2], [3, 3]]

【讨论】:

    【解决方案2】:

    使用[Int: [Int]] 字典来跟踪键指定值的最大数组。

    let arrays = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
    var largest = [Int: [Int]]()
    
    for arr in arrays {
        // Get the first value from the array
        if let first = arr.first {
    
            // current is the count for that key already in dictionary largest
            // If the key isn't found, the nil coalescing operator ?? will
            // return the default count of 0.
            let current = largest[first]?.count ?? 0
    
            // If our new array has a larger count, put it in the dictionary
            if arr.count > current {
                largest[first] = arr
            }
        }
    }
    
    // Convert the dictionary's values to an array for the final answer.   
    let result = Array(largest.values)
    
    print(result)  // [[5], [7], [2, 2, 2], [3, 3]]
    

    同样的逻辑可以与reduce一起使用,在一行中提供结果:

    let result = arrays.reduce([Int: [Int]]()) { var d = $0; guard let f = $1.first else { return d }; d[f] = d[f]?.count > $1.count ? d[f] : $1; return d }.map { $1 }
    

    替代版本

    此版本使用[Int: Int] 字典来保存为每个键找到的最大数组的计数,然后使用数组构造函数在最后重建数组。

    let arrays = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
    var counts = [Int: Int]()
    
    for arr in arrays {
        if let first = arr.first {
            counts[first] = max(counts[first] ?? 0, arr.count)
        }
    }
    
    let result = counts.map { [Int](count: $1, repeatedValue: $0) }
    
    print(result)  // [[5], [7], [2, 2, 2], [3, 3]]
    

    同样的逻辑可以与reduce一起使用,在一行中提供结果:

    let result = arrays.reduce([Int: Int]()) { var d = $0; guard let f = $1.first else { return d }; d[f] = max(d[f] ?? 0, $1.count); return d }.map { [Int](count: $1, repeatedValue: $0) }
    

    【讨论】:

      【解决方案3】:

      当我看到 vacawama 的回复非常相似时,我正要写下我的答案。决定回到它只是因为它是一个有趣的问题。因此,我的替代方案几乎可以肯定比 vacawama 的解决方案慢得多,并且不保留顺序,但我认为作为在 Swift 中解决此类问题的替代方案示例,我认为这很有趣。

      var items = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
      
      let reduced = items.sort({
              let lhs = $0.first, rhs = $1.first
              return lhs == rhs ? $0.count > $1.count : lhs < rhs
          }).reduce( [[Int]]()) { (res, items) in
              return res.last?.last != items.last ? res + [items] : res
          }
      
      print(reduced)  // [[2, 2, 2], [3, 3], [5], [7]]
      

      或者,如果您宁愿将所有内容都塞在一行中:

      var items = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
      
      let reduced = items.sort({ let lhs = $0.first, rhs = $1.first; return lhs == rhs ? $0.count > $1.count : lhs < rhs }).reduce([[Int]]()) { $0.last?.last != $1.last ? $0 + [$1] : $0 }
      
      print(reduced)  // [[2, 2, 2], [3, 3], [5], [7]]
      

      【讨论】:

        猜你喜欢
        • 2020-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-26
        • 1970-01-01
        • 2019-04-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多