Swiftには_.findWhereのようなものがありますか Underscore.jsのますか?
タイプの構造体のT
配列があり、name
プロパティがに等しい構造体オブジェクトが配列に含まれているかどうかを確認したいと思いますFoo
。
使用しようfind()
としましたfilter()
が、String
またはなどのプリミティブ型でのみ機能しInt
ます。Equitable
プロトコルに準拠していないなどのエラーをスローします。
Swiftには_.findWhereのようなものがありますか Underscore.jsのますか?
タイプの構造体のT
配列があり、name
プロパティがに等しい構造体オブジェクトが配列に含まれているかどうかを確認したいと思いますFoo
。
使用しようfind()
としましたfilter()
が、String
またはなどのプリミティブ型でのみ機能しInt
ます。Equitable
プロトコルに準拠していないなどのエラーをスローします。
回答:
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"
が1つの操作を$0.name == "boo"
実行し、別の操作を 実行するかどうかを確認する必要があると言い ます
あなたは使用することができますindex
上で利用できる方法をArray
(述語とここでは、Appleのドキュメントを参照してください)。
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]
}
スウィフト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
}
でスウィフト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
要求された要素を返すだけで、フィルタリングされた要素の完全に新しい配列を作成します。
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
}
スウィフト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]
}
$0.name == "Foo"
か?
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
}
または、コメントでマーティンが指摘したことをfilter
試して、もう一度試してみてください:配列内のプロパティを使用してオブジェクトを検索する。
item
は、配列内のitemと同じタイプであると想定しています。ただし、私が持っているのはからのタイトルだけview.annotation.title
です。このタイトルで配列内の項目を比較する必要があります。
if contains(yourArray, view.annotation.title) { // code goes here }
。
スウィフト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