在数组中找到一个对象?

Swift 在 Underscore.js 中有类似 找到哪里的东西吗?

我有一个类型为 T的结构体数组,想要检查数组是否包含一个属性为 name等于 Foo的结构体对象。

尝试使用 find()filter(),但它们只适用于基本类型,例如 StringInt。抛出一个关于不符合 Equitable协议或类似的错误。

225837 次浏览

使用 contains:

var yourItem:YourType!
if contains(yourArray, item){
yourItem = item
}

或者你可以试试 Martin 在评论中指出的方法,再试一次 filter: 在数组中查找具有属性的对象

您可以 过滤器数组,然后只选择第一个元素,如图所示 在 在数组中查找具有属性的对象

或者定义自定义扩展

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
}

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]
}

可以使用 Array上可用的带谓词(点击这里查看苹果的文档)的 index方法。

func index(where predicate: (Element) throws -> Bool) rethrows -> Int?

对于你的具体例子,这将是:

Swift 5.0

if let i = array.firstIndex(where: { $0.name == "Foo" }) {
return array[i]
}

Swift 3.0

if let i = array.index(where: { $0.name == Foo }) {
return array[i]
}

Swift 2.0

if let i = array.indexOf({ $0.name == Foo }) {
return array[i]
}

Swift 3.0

if let index = array.index(where: { $0.name == "Foo" }) {
return array[index]
}

Swift 2.1

Swift 2.1现在支持对象属性的过滤。您可以根据结构或类的任何值对数组进行筛选,这里是一个示例

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 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
}

斯威夫特2或更晚

您可以将 indexOfmap组合起来,在一行中编写一个“ find element”函数。

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看起来很复杂,但是当在数组中找到第一个匹配项时,计算就会停止。这两种方法各有利弊。

Swift 3

您可以在 Swift 3中使用 index (where:)

func index(where predicate: @noescape Element throws -> Bool) rethrows -> Int?

例子

if let i = theArray.index(where: {$0.name == "Foo"}) {
return theArray[i]
}

Swift 3

如果你需要这个对象,使用:

array.first{$0.name == "Foo"}

(如果您有多个名为“ Foo”的对象,那么 first将从未指定的顺序返回第一个对象)

另一种访问 array.index (of: Any)的方法是声明对象

import Foundation
class Model: NSObject {  }

在 Swift 中使用 Lo-Dash 或 Underscore.js 的 一美元:

import Dollar


let found = $.find(array) { $0.name == "Foo" }

Swift 3

if yourArray.contains(item) {
//item found, do what you want
}
else{
//item not found
yourArray.append(item)
}

斯威夫特3:

您可以使用 Swifts 内置的功能来查找 Array 中的自定义对象。

首先,必须确保自定义对象符合: 等价协议

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)
}
}

通过在对象中添加 Equtable 功能,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

对于 Swift 3来说,

let index = array.index(where: {$0.name == "foo"})

斯威夫特,

另一种方式来实现这一点 使用过滤器函数,

if let object = elements.filter({ $0.title == "title" }).first {
print("found")
} else {
print("not found")
}

例如,如果我们有一个数字数组:

let numbers = [2, 4, 6, 8, 9, 10]

我们可以找到第一个这样的奇数:

let firstOdd = numbers.index { $0 % 2 == 1 }

这将返回4作为一个可选的整数,因为第一个奇数(9)在索引4处。