我试图在数组中添加扩展方法,如下所示:
extension Array {
func contains(obj: T) -> Bool {
let filtered = self.filter {$0 == obj}
return filtered.count > 0
}
}
但是self.filter {$0 == obj}
不起作用。编译器错误:
无法找到' =='接受提供的参数
答案 0 :(得分:32)
您实际上并不需要编写扩展程序,您可以使用Swift库中的全局函数contains
:
contains([1,2,3], 1)
答案 1 :(得分:13)
正如我在评论中提到的,有一个contains
功能。但是要回答如何编写扩展以及编译器错误意味着什么的问题:
数组中的元素无法与==
进行比较。您需要确保参数为Equatable
,并且需要确保数组元素的类型相同。
extension Array {
func contains<T : Equatable>(obj: T) -> Bool {
let filtered = self.filter {$0 as? T == obj}
return filtered.count > 0
}
}
Swift 2包含SequenceType.contains
,这正是您尝试创建的内容。
这可以通过Swift语法实现,该语法允许将方法限制为某些(例如Equatable)类型参数。它看起来像这样:
extension SequenceType where Generator.Element: Equatable {
func contains(element: Self.Generator.Element) -> Bool {
...
}
}
答案 2 :(得分:1)
我发现内置包含不适用于引用类型。我需要这个并使用下面的代码解决它。我在这里粘贴它是因为其他人可能会像我一样对contains()感到困惑。
extension Array {
func containsReference(obj: AnyObject) -> Bool {
for ownedItem in self {
if let ownedObject: AnyObject = ownedItem as? AnyObject {
if (ownedObject === obj) {
return true
}
}
}
return false
}
}
答案 3 :(得分:1)
这适用于Swift 2.1的参考类型非常好。
extension SequenceType where Generator.Element: AnyObject {
func contains(obj: Self.Generator.Element?) -> Bool {
if obj != nil {
for item in self {
if item === obj {
return true
}
}
}
return false
}
}
对于值类型,您可以添加:
extension SequenceType where Generator.Element: Equatable {
func contains(val: Self.Generator.Element?) -> Bool {
if val != nil {
for item in self {
if item == val {
return true
}
}
}
return false
}
}
答案 4 :(得分:0)
不完美,但是基于nschum's answer构建的这个版本也支持可选参数(尽管不是带有可选类型的数组):
extension Array {
private func typeIsOptional() -> Bool {
return reflect(self[0]).disposition == .Optional
}
func contains<U : Equatable>(obj: U) -> Bool {
if isEmpty {
return false
}
if (typeIsOptional()) {
NSException(name:"Not supported", reason: "Optional Array types not supported", userInfo: nil).raise()
}
// cast type of array to type of argument to make it equatable
for item in self.map({ $0 as? U }) {
if item == obj {
return true
}
}
return false
}
// without this version, contains("foo" as String?) won't compile
func contains<U : Equatable>(obj: U?) -> Bool {
if isEmpty {
return false
}
if (typeIsOptional()) {
NSException(name:"Not supported", reason: "Optional Array types not supported", userInfo: nil).raise()
}
return obj != nil && contains(obj!)
}
}
如果您有一个选项数组,您可以使用此全局函数thanks to jtbandes获取非选项(删除了nil个参数)的副本:
func unwrapOptionals<T>(a: [T?]) -> [T] {
return a.filter { $0 != nil }.map { $0! }
}
用法:
1> func unwrapOptionals<T>(a: [T?]) -> [T] {
2. return a.filter { $0 != nil }.map { $0! }
3. }
4>
5> let foo = ["foo" as String?]
foo: [String?] = 1 value {
[0] = "foo"
}
6> let bar = unwrapOptionals(foo)
bar: [String] = 1 value {
[0] = "foo"
}
为了更好地衡量,如果类型不是可选的,请添加一个只返回数组的数组。这样,如果在非可选数组上调用unwrapOptionals()
,则可以避免运行时错误:
func unwrapOptionals<T>(a: [T]) -> [T] {
return a
}
请注意,您可能认为可以在unwrapOptionals
内拨打func contains<U : Equatable>(obj: U?)
。但是,这不起作用,因为Array扩展中的Element
类型只是一种类型 - 它不“知道”它是一个可选类型。所以如果你打电话给unwrapOptionals
,第二个版本就会被调用,你只需要把阵列装回选项。