一尘不染

Set()的Swift map(_ :)扩展名?

swift

  let numberSet = Set(1...11)
  let divideSet = numberSet.map({  $0 / 10 }) 
  //Error: Set does not have a member named map   :(

Swift 1.2支持Set()无序集合,但map(_:)似乎在Sets上不起作用,因此我决定在操场上变聪明并尝试:

 let stringSet = Set(map(numberSet, { String($0)}))
 println(stringSet)
 stringSet =  ["2", "11", "1", "8", "6", "4", "3", "9", "7", "10", "5]

这似乎有效。所以我尝试扩展Set:

    extension Set {
        func map<U>(transform: (T) -> U) -> Set<U> {
        return Set(Swift.map(self, transform))  }
    }
   Error: "couldn't find initialiser for Set(T) that accepts argument of type U"

而且我认为有一个很好的理由为什么它不起作用,例如这里的示例:

   let smarDividSet = Set(map(numberSet, {$0 / 2})) 
   println(smarDividSet)
   smartDividSet = "[5, 0, 2, 4, 1, 3]” 
  //Somehow elements is the Set are going missing.

关于如何扩展Set以可靠地使用map(_ :)的任何想法?谢谢大家


阅读 266

收藏
2020-07-07

共1个答案

一尘不染

更新: Swift 2和3进行了很多更改。的通用占位符Set现在ElementT,而不是,并且所有集合都有一个map()返回
数组 的方法

对于Set -> Set映射的问题(例如,将不同的元素映射到相同的结果)也给出了很好的论据。另一方面,可能会有这种映射的用例,因此这是 Swift
3
的更新(现在使用其他名称)。

extension Set {
    func setmap<U>(transform: (Element) -> U) -> Set<U> {
        return Set<U>(self.lazy.map(transform))
    }
}

例:

let numberSet = Set(1...11)
let divideSet = numberSet.setmap { $0 / 2 }
print(divideSet) // [5, 0, 2, 4, 1, 3]

(旧答案:) 您快到了。由于某些原因,必须显式指定返回集的通用类型:

extension Set {
    func map<U>(transform: (T) -> U) -> Set<U> {
        return Set<U>(Swift.map(self, transform))
    }
}

例:

let numberSet = Set(1...11)

let divideSet = numberSet.map { $0 / 2 }
println(divideSet) // [5, 0, 2, 4, 1, 3]

由于整数除法会$0 / 2 截断 商,因此结果集中的元素较少 ,例如4/2和5/2都映射到同一元素2。对于浮点除法不会发生这种情况:

let floatdivideSet = numberSet.map { Double($0) / 2.0 }
println(floatdivideSet) // [4.0, 5.0, 4.5, 5.5, 2.0, 3.0, 3.5, 2.5, 1.5, 1.0, 0.5]

另一个可能的实现是

extension Set {
    func map<U>(transform: (T) -> U) -> Set<U> {
        return Set<U>(lazy(self).map(transform))
    }
}

在此lazy(self)返回LazyForwardCollection具有map()方法的,并LazyForwardCollection再次返回。优点可能是不创建任何中间数组。

2020-07-07