Swift是否有类似_.findWhere的内容中的内容?
我有一个类型为struct的数组,T
想检查array是否包含name
属性等于的struct对象Foo
。
尝试使用 find()
,filter()
但它们仅适用于基本类型,例如String
或Int
。引发有关不符合Equitable
协议之类的错误。
Swift是否有类似_.findWhere的内容中的内容?
我有一个类型为struct的数组,T
想检查array是否包含name
属性等于的struct对象Foo
。
尝试使用 find()
,filter()
但它们仅适用于基本类型,例如String
或Int
。引发有关不符合Equitable
协议之类的错误。
Answers:
FWIW,如果您不想使用自定义功能或扩展名,则可以:
let array = [ .... ]
if let found = find(array.map({ $0.name }), "Foo") {
let obj = array[found]
}
name
首先生成数组,然后find
从中。
如果阵列很大,则可能需要执行以下操作:
if let found = find(lazy(array).map({ $0.name }), "Foo") {
let obj = array[found]
}
或许:
if let found = find(lazy(array).map({ $0.name == "Foo" }), true) {
let obj = array[found]
}
SWIFT 5
检查元素是否存在
if array.contains(where: {$0.name == "foo"}) {
// it exists, do something
} else {
//item could not be found
}
获取元素
if let foo = array.first(where: {$0.name == "foo"}) {
// do something with foo
} else {
// item could not be found
}
获取元素及其偏移量
if let foo = array.enumerated().first(where: {$0.element.name == "foo"}) {
// do something with foo.offset and foo.element
} else {
// item could not be found
}
获取偏移
if let fooOffset = array.firstIndex(where: {$0.name == "foo"}) {
// do something with fooOffset
} else {
// item could not be found
}
$0.name == "foo"
执行一项操作并 $0.name == "boo"
执行另一项操作
您可以使用谓词index
上可用的方法Array
(请参阅此处的Apple文档)。
func index(where predicate: (Element) throws -> Bool) rethrows -> Int?
对于您的特定示例,这将是:
斯威夫特5.0
if let i = array.firstIndex(where: { $0.name == "Foo" }) {
return array[i]
}
斯威夫特3.0
if let i = array.index(where: { $0.name == Foo }) {
return array[i]
}
雨燕2.0
if let i = array.indexOf({ $0.name == Foo }) {
return array[i]
}
迅捷3
如果需要该对象,请使用:
array.first{$0.name == "Foo"}
(如果有多个名为“ Foo” first
的对象,则将以未指定的顺序返回第一个对象)
array.first {$0.name == "Foo"}
array.first(where: {$0.name == "Foo"})
您可以过滤数组,然后选择第一个元素,如“ 在数组中查找带有属性的对象”中所示。
或者您定义自定义扩展
extension Array {
// Returns the first element satisfying the predicate, or `nil`
// if there is no matching element.
func findFirstMatching<L : BooleanType>(predicate: T -> L) -> T? {
for item in self {
if predicate(item) {
return item // found
}
}
return nil // not found
}
}
用法示例:
struct T {
var name : String
}
let array = [T(name: "bar"), T(name: "baz"), T(name: "foo")]
if let item = array.findFirstMatching( { $0.name == "foo" } ) {
// item is the first matching array element
} else {
// not found
}
在Swift 3中,您可以使用现有first(where:)
方法(如注释中所述):
if let item = array.first(where: { $0.name == "foo" }) {
// item is the first matching array element
} else {
// not found
}
array.lazy.filter( predicate ).first
呢?.lazy对于小型阵列的效率如何?
filter
总是复杂的,O(n)
而在情况中findFirstMatching
,只有在最坏的情况下(当您要查找的元素是数组中的最后一个或根本不在数组中时),它总是很复杂的。2. filter
创建一个全新的过滤元素数组,而findFirstMatching
刚刚返回所请求的元素。
斯威夫特3.0
if let index = array.index(where: { $0.name == "Foo" }) {
return array[index]
}
斯威夫特2.1
swift 2.1现在支持对象属性过滤。您可以根据struct或class的任何值过滤数组,这是一个示例
for myObj in myObjList where myObj.name == "foo" {
//object with name is foo
}
要么
for myObj in myObjList where myObj.Id > 10 {
//objects with Id is greater than 10
}
Swift 2或更高版本
您可以合并indexOf
并map
在一行中编写“查找元素”功能。
let array = [T(name: "foo"), T(name: "Foo"), T(name: "FOO")]
let foundValue = array.indexOf { $0.name == "Foo" }.map { array[$0] }
print(foundValue) // Prints "T(name: "Foo")"
使用filter
+ first
看起来更干净,但是会filter
评估数组中的所有元素。indexOf
+ map
看起来很复杂,但是当找到数组中的第一个匹配项时,评估就会停止。两种方法都各有利弊。
用途contains
:
var yourItem:YourType!
if contains(yourArray, item){
yourItem = item
}
或者,您可以尝试在注释中尝试Martin指出的内容,然后filter
再尝试一次:在Array中查找具有Property的对象。
item
与数组中的项具有相同的类型。但是,我所拥有的只是的标题view.annotation.title
。我需要按此标题比较数组中的项目。
if contains(yourArray, view.annotation.title) { // code goes here }
。
斯威夫特3:
您可以使用Swifts内置功能在数组中查找自定义对象。
首先,您必须确保您的自定义对象符合:Equatable protocol。
class Person : Equatable { //<--- Add Equatable protocol
let name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
//Add Equatable functionality:
static func == (lhs: Person, rhs: Person) -> Bool {
return (lhs.name == rhs.name)
}
}
将Equatable功能添加到对象后,Swift现在将向您显示可在数组上使用的其他属性:
//create new array and populate with objects:
let p1 = Person(name: "Paul", age: 20)
let p2 = Person(name: "Mike", age: 22)
let p3 = Person(name: "Jane", age: 33)
var people = [Person]([p1,p2,p3])
//find index by object:
let index = people.index(of: p2)! //finds Index of Mike
//remove item by index:
people.remove(at: index) //removes Mike from array