Swift泛型问题

7

现在,我想要能够查看一个对象是否包含在一个Array中:

func isIncluded<U:Comparable>(isIncluded : U) -> Bool
{
    for item in self
    {
        if (item == isIncluded)
        {
            return true
        }
    }

    return false
}

如果你注意到这个函数属于一个Array扩展。问题是如果将它添加到这里:
extension Array{

}

我收到以下错误信息:

找不到接受提供的参数的'=='的重载

enter image description here

我理解可能需要告诉Array中应该包含什么类型的对象,例如:T[] <T.GeneratorType.Element: Comparable>。但是它也不起作用:

块语句是未使用的闭包
非名义类型“T []”不能被扩展
扩展中缺少'{'

enter image description here

3个回答

8

使用Swift编程,我们需要思考是否有一个函数可以在类方法之外完成任务。

就像在这里的情况一样:

contains(theArray, theItem)

您可以在游乐场中尝试它:

let a = [1, 2, 3, 4, 5]
contains(a, 3)
contains(a, 6)

我通过在Swift符号(例如:Array)上按cmd键找到了许多这些函数,然后浏览包含所有声明Swift一般类和函数的全局文件。

这里有一个小扩展程序,将为所有数组添加“contains”方法:

extension Array {
    func contains<T: Equatable>(item: T) -> Bool {
        for i in self {
            if item == (i as T) { return true }
        }
        return false
    }
}

我一直在做这个,我知道它的存在,但我更喜欢使用theArray.contains(element)而不是contains(theArray,element) - Rui Peres
1
@JackyBoy 我创建了一个小扩展来满足你的愿望 :) - Jean Le Moignan
请注意,您需要使用可选类型转换:if item == (i as? T),以便在类型不匹配数组项类型时不会崩溃。此外,此方法不适用于可选对象的数组(即String?[])。 - John Estropia
@JohnEstropia John,你说的关于可选项的问题肯定是对的...我还没有找到一个通用的解决方案... - Jean Le Moignan
@JeanLeMoignan 请查看我的答案,这是一个通用的解决方案。 - wbennett

3

需要补充的是,问题在于T已经被定义,并且数组对T的定义不符合Equatable的要求。你可以通过强制转换(就像被接受的答案)来实现你想要的功能,但这样会冒着无效转换的风险,或者你可以传入一个委托,这样就不需要进行任何转换。

考虑修改如下:

extension Array {
   func contains(comparator: (T)->Bool) -> Bool {
    for item in self {
        if comparator(item) {
           return true
        }
    }
    return false
  }
}

使用示例:

class Test {
    func arrayContains(){
        var test: Int[] = [0,1,3,4,5]
        //should be true 
        var exists = test.contains({(item)->Bool in item == 0});
    }
}

由于“Any”未实现Equatable,因此这是一个很好的方法。一个更简洁的例子是“assert([”one“,”two“] .contains({$0 ==”one“}))”。 - John Vasileff

2

虽然不是说不可能,但我还没有看到一种方式能够扩展结构体或类以在原始泛型类型上设置条件,例如保证数组具有 EquatableComparable。然而,针对你的特定问题,你可以尝试以下做法:

var arr = [1, 2, 3]
var isIncluded : Bool = arr.bridgeToObjectiveC().doesContain(1) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接