在数组中查找对象?

时间:2015-02-25 19:25:45

标签: ios swift

Swift在Underscore.js中有类似_.findWhere的内容吗?

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

尝试使用find()filter(),但它们仅适用于原始类型,例如StringInt。引发错误,指出不符合Equitable协议或类似协议。

16 个答案:

答案 0 :(得分:216)

SWIFT 3/4/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
}

答案 1 :(得分:117)

您可以使用index上的Array方法和谓词(see Apple's documentation here)。

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

对于您的具体示例,这将是:

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

答案 2 :(得分:80)

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

答案 3 :(得分:38)

Swift 3

如果您需要使用对象:

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

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

答案 4 :(得分:20)

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
}

OR

for myObj in myObjList where myObj.Id > 10 {
 //objects with Id is greater than 10
}

答案 5 :(得分:18)

您可以过滤数组,然后选择第一个元素,如图所示 在Find Object with Property in Array

或者您定义自定义扩展程序

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:)方法 (作为mentioned in a comment):

if let item = array.first(where: { $0.name == "foo" }) {
    // item is the first matching array element
} else {
    // not found
}

答案 6 :(得分:8)

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

答案 7 :(得分:7)

Swift 4

实现这一目标的另一种方法 使用过滤功能,

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

答案 8 :(得分:3)

Swift 3

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

答案 9 :(得分:2)

Swift 2或更高版本

您可以合并indexOfmap来编写&#34;查找元素&#34;功能在一条线上。

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

答案 10 :(得分:1)

使用contains

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

或者您可以在评论中尝试Martin指出的内容并再次尝试filterFind Object with Property in Array

答案 11 :(得分:1)

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

import Foundation
class Model: NSObject {  }

答案 12 :(得分:1)

使用Dollar作为Swift的Lo-Dash或Underscore.js:

plot <- read_csv("AFGP60 UV-05-04-16.csv", 
               col_names = FALSE, na = "null", skip = 2,n_max = numrow)
diffplot <- c(plot[1:601,2])
diffplot <- lapply(diffplot,as.double)
findpeaks(diffplot)`

答案 13 :(得分:1)

斯威夫特3:

您可以使用Swifts内置功能在阵列中查找自定义对象。

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

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

答案 14 :(得分:1)

对于Swift 3,

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

答案 15 :(得分:0)

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

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

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

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

这将作为可选整数发送回4,因为第一个奇数(9)位于索引4。