我正在尝试编写一个简单的数组扩展,它提供了一个独特的'方法。以下是我到目前为止的情况:
extension Array {
func distinct() -> T[] {
var rtn = T[]()
for x in self {
var containsItem = contains(rtn, x)
if !containsItem {
rtn.append(x)
}
}
return rtn
}
}
问题在于'包含'声明失败如下:
无法找到'包含'接受提供的参数
我很确定类型约束是正确的。有什么想法吗?
答案 0 :(得分:13)
array
中的元素不一定是Equatable
,即它们与==
不具有可比性。
这意味着您无法为所有可能的数组编写该函数。 Swift不允许您只扩展数组的子集。
这意味着你应该把它写成一个单独的函数(这可能也是contains
不是方法的原因。)
let array = ["a", "b", "c", "a"]
func distinct<T: Equatable>(array: [T]) -> [T] {
var rtn = [T]()
for x in array {
var containsItem = contains(rtn, x)
if !containsItem {
rtn.append(x)
}
}
return rtn
}
distinct(array) // ["a", "b", "c"]
Swift 2支持限制对协议实现子集的扩展,因此现在允许以下内容:
let array = ["a", "b", "c", "a"]
extension SequenceType where Generator.Element: Comparable {
func distinct() -> [Generator.Element] {
var rtn: [Generator.Element] = []
for x in self {
if !rtn.contains(x) {
rtn.append(x)
}
}
return rtn
}
}
array.distinct() // ["a", "b", "c"]
请注意Apple如何使用相同的语法添加SequenceType.contains
。
答案 1 :(得分:5)
终于找到了如何做到这一点:
extension Array {
func contains<T : Equatable>(obj: T) -> Bool {
return self.filter({$0 as? T == obj}).count > 0
}
func distinct<T : Equatable>(_: T) -> T[] {
var rtn = T[]()
for x in self {
if !rtn.contains(x as T) {
rtn += x as T
}
}
return rtn
}
}
使用/测试:
let a = [ 0, 1, 2, 3, 4, 5, 6, 1, 2, 3 ]
a.contains(0)
a.contains(99)
a.distinct(0)
不幸的是,我无法找到一种方法来做到这一点,而无需指定随后被忽略的参数。它唯一的原因就是调用正确的形式。这种方法对distinct
的主要优点似乎是它没有将像distinct
这样的常用术语转储到全局命名空间中。对于包含情况,它看起来更自然。
答案 2 :(得分:2)
另一个解决方案是使用find(Array:[T],obj:T)函数。它将返回一个可选的Int,所以你可以做的是
if let foundResult = find(arr, obj) as Int
{
//obj is contained in arr
} else
{
//obj is not contained in arr.
}
答案 3 :(得分:2)
从Swift 2开始,这可以通过协议扩展方法来实现,
例如在符合SequenceType
顺序的所有类型上
元素符合Equatable
:
extension SequenceType where Generator.Element : Equatable {
func distinct() -> [Generator.Element] {
var rtn : [Generator.Element] = []
for elem in self {
if !rtn.contains(elem) {
rtn.append(elem)
}
}
return rtn
}
}
示例:
let items = [1, 2, 3, 2, 3, 4]
let unique = items.distinct()
print(unique) // [1, 2, 3, 4]
如果元素被进一步限制为Hashable
那么你
可以利用Set
类型:
extension SequenceType where Generator.Element : Hashable {
func distinct() -> [Generator.Element] {
return Array(Set(self))
}
}