অ্যারেতে একটি অবজেক্ট সন্ধান করবেন?


144

অ্যান্ডসকোর.জেএস-সুইডের কি _.ফাইন্ডের মতো কিছু রয়েছে ?

আমার ধরণের স্ট্রাক্টের একটি অ্যারে রয়েছে Tএবং অ্যারেতে এমন স্ট্রাক্ট অবজেক্ট রয়েছে যার nameসম্পত্তি সমান কিনা তা পরীক্ষা করে দেখতে চাই Foo

ব্যবহারের চেষ্টা করা হয়েছিল find()এবং filter()তারা কেবল প্রাথমিক প্রকারের সাথে কাজ করে, যেমন Stringবা IntEquitableপ্রোটোকল বা এর মতো কিছু না মেনে চলার বিষয়ে একটি ত্রুটি ফেলে ।



কেন nsdictionary রূপান্তর এবং অনুসন্ধান
সাধারণ ধনুক

3
আমি বিশ্বাস করি স্যুইফ্ট ২.০ এ আর পাওয়া যায় না .. আমি প্রায় ১.২ কোডকে সুইফট ২.০ তে রূপান্তর করছি এবং এর পরিবর্তে সূচিপত্র ব্যবহার করার কথা বলেছে।
সুইফ্ট সোডা

উত্তর:


91

এফডব্লিউআইডাব্লু, আপনি যদি কাস্টম ফাংশন বা এক্সটেনশন ব্যবহার করতে না চান তবে আপনি এটি করতে পারেন:

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

এটি আরও ভাল। আমি এটি উত্তর হিসাবে চিহ্নিত করব কারণ এটি সামগ্রিকভাবে সহজ দেখায় এবং এটির জন্য কোনও কাস্টম ফাংশন তৈরির প্রয়োজন হয় না।
সাহাত ইয়ালকাবভ

27
সুইফট ২.০ হিসাবে আপনি ব্যবহার করতে পারেন: array.indexOf ({$ 0.name == "Foo"})
tf.alves

73
সুইফট ৩.০ হিসাবে আপনি ব্যবহার করতে পারেন: অ্যারে.ফার্স্ট (যেখানে: {$ 0.name == "ফু"}) যদি আপনার প্রয়োজন হয়
ব্রেট

আমি কীভাবে check 0. চেক করতে পারি "নামের" স্ট্রিংটিতে "ফু" আছে? উত্তরগুলি হুবহু মিলের বিষয়ে। আমার স্ট্রিং থাকা দরকার যে কেউ এর জন্য বাক্য গঠন দিতে পারে
আজিক আবদুল্লাহ

289

সুইফট 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
}

6
দুর্দান্ত সুইফট-স্টাইলের উত্তর!
জোল্টন

4
ধন্যবাদ আপনি আমার সেভার এটি আমার কোডটি অনেক পরিষ্কার করেছে
এডি অগ্রগতি

একাধিক শর্ত কীভাবে চেক করবেন বলুন যে অ্যারে $0.name == "foo"একটি অপারেশন করে এবং $0.name == "boo" অন্য অপারেশন করে
কিনা তা আমাকে খতিয়ে দেখা দরকার

এটি আমাকে ২০২০
সিসিলোক ২

আমি কীভাবে check 0. চেক করতে পারি "নামের" স্ট্রিংটিতে "ফু" আছে? যে কেউ এর জন্য বাক্য গঠন দিতে পারে
আজিক আবদুল্লাহ

131

আপনি প্রিকিকেটের সাথে indexউপলভ্য পদ্ধতিটি ব্যবহার করতে পারেন Array( অ্যাপলের ডকুমেন্টেশনটি এখানে দেখুন )।

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

সুইফট ২.০

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

3
হ্যাঁ এটি কেবল সুইফট ২.০ নিয়ে কাজ করে। দুঃখিত এটি উল্লেখ করা উচিত ছিল।
ব্যবহারকারী 3799504

@ ইউজার 3799504 $ 0 এর অর্থ?
প্রমোদ তপানিয়া

বন্ধ হওয়ার প্রথম যুক্তির জন্য short 0 সংক্ষেপণ hand এই ক্ষেত্রে এটি স্ব.জেনারেটর.ইলেমেন্ট বা অ্যারের প্রতিটি উপাদানকে বোঝায়। দয়া করে দেখুন: বিকাশকারী
অ্যাপ্লিকেশন

1
সুইফট 3 কেমন?
অ্যাডনাকো

38

সুইফট 3

আপনার যদি প্রয়োজন অবজেক্ট ব্যবহার করুন:

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

(আপনার যদি "ফু" নামে একাধিক অবজেক্ট থাকে তবে firstঅনির্দিষ্ট অর্ডার থেকে প্রথম অবজেক্টটি ফিরিয়ে দেবে)


এই জন্য আপনাকে ধন্যবাদ. এটি সেখানে যেতে হবে!
Nerdy থেরাপিস্ট

3
এটি দুর্দান্ত, আপনাকে ধন্যবাদ! এটিও এর মতো লেখা যেতে পারে:array.first {$0.name == "Foo"}
রোল্যান্ড টি

2
ইন Swift3 এটা হতে হবেarray.first(where: {$0.name == "Foo"})
ড্যানিয়েল

ড্যানিয়েলের নোটের সাথে, এটি সুইফট ৩-এর সঠিক, সেরা উত্তর this এই উদ্দেশ্যে মানচিত্র, ফিল্টার ব্যবহার করবেন না; তারা পুরো সংগ্রহগুলিতে পুনরাবৃত্তি করে, যা প্রচুর অপব্যয়যোগ্য হতে পারে।
ওম্বল

20

আপনি অ্যারে ফিল্টার করতে পারেন এবং তারপরে ঠিক প্রথম উপাদানটি বাছাই করতে পারেন , অ্যারেতে সম্পত্তি সহ অবজেক্টটি দেখানো হয়েছে

অথবা আপনি একটি কাস্টম এক্সটেনশন সংজ্ঞায়িত করেন

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স্রেফ অনুরোধকৃত উপাদানটি দেয়।
0101

সুইফ্ট 3-এ, আমি এই এক্সটেনশন পদ্ধতির জন্য নন-প্রোটোকল, নন-ক্লাসের ধরণের 'বুল' এবং অঘোষিত প্রকার 'টি' ব্যবহারের ত্রুটিগুলি উত্তরাধিকার সূচনা করছি ।
ইসুরু

@ ইসুরু: এই উত্তরটি বেশ পুরানো ছিল এবং এটি একটি পুরানো সুইফ্ট সংস্করণে উল্লেখ করা হয়েছিল। সুইফ্ট 3-এ আপনার আর কাস্টম এক্সটেনশন পদ্ধতির প্রয়োজন নেই, আমি সেই অনুযায়ী উত্তর আপডেট করেছি।
মার্টিন আর

20

সুইফট 3.0

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

সুইফট 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
}

9

সুইফট 4 ,

ফিল্টার ফাংশন ব্যবহার করে এটি অর্জনের আর একটি উপায়,

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

8

সুইফট 3

আপনি সুইফট 3 তে সূচক (যেখানে :) ব্যবহার করতে পারেন

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

উদাহরণ

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

সুইফ্ট 3-এ এমন কোনও পদ্ধতি আছে যেখানে আপনি শর্ত পূরণ করে এমন অ্যারে আইটেমগুলির একটি সাবলিস্টের সূচকগুলি খুঁজে পেতে পারেন $0.name == "Foo"?
আহমেদ খেদার

3

সুইফট 3

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

2

সুইফট 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জটিল দেখায় তবে অ্যারেতে প্রথম ম্যাচটি পাওয়া গেলে মূল্যায়ন বন্ধ হয়ে যায়। উভয় পদ্ধতিরই পক্ষে মতামত রয়েছে।


1

ব্যবহার contains:

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

অথবা আপনি মার্টিন মন্তব্যে আপনাকে যে বিষয়টির দিকে লক্ষ্য করেছেন, সেটিকে চেষ্টা করে দেখতে পারেন এবং filterআরেকবার চেষ্টা করতে পারেন: সম্পত্তির সাথে অ্যারেটিতে অনুসন্ধান করুন


এটি কি কেবল একটি বুলিয়ান ফেরত দেবে? আমারও খুব ভাল জিনিসটি পাওয়া উচিত, কেবল অ্যারেতে রয়েছে কিনা তা পরীক্ষা করে দেখুন।
সাহাত ইয়ালকাবভ

এই অনুমানটি itemঅ্যারের আইটেমের মতো একই ধরণের। যাইহোক, আমার সমস্ত কিছুই কেবল একটি শিরোনাম view.annotation.title। আমি এই শিরোনাম দ্বারা অ্যারে আইটেম তুলনা প্রয়োজন।
সাহাত ইয়ালকাবভ

কিছু একটা if contains(yourArray, view.annotation.title) { // code goes here }
সাহাত ইয়ালকাবভ

মন্তব্যে মার্টিন আপনাকে অন্য একটি উপায় দেখিয়েছে। তিনি প্রদত্ত লিঙ্কটি পরীক্ষা করুন।
খ্রিস্টান

1

অ্যারে.ইন্ডেক্স (এর যে কোনও) এর অ্যাক্সেস পাওয়ার আরও একটি উপায় হ'ল আপনার অবজেক্টটি ঘোষণা করে

import Foundation
class Model: NSObject {  }


1

সুইফট 3:

আপনি কোনও অ্যারেতে কাস্টম অবজেক্টগুলি সন্ধান করতে কার্যকার্যে নির্মিত সুইফট ব্যবহার করতে পারেন।

প্রথমে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনার কাস্টম অবজেক্টটি: সমতুল্য প্রোটোকলের সাথে সঙ্গতিপূর্ণ

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

আপনার বস্তুতে সমতুল্য কার্যকারিতা যুক্ত হওয়ার সাথে সাথে, সুইফট এখন আপনাকে অতিরিক্ত বৈশিষ্ট্যগুলি প্রদর্শন করবে যা আপনি অ্যারেতে ব্যবহার করতে পারবেন:

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


0

উদাহরণস্বরূপ, যদি আমাদের সংখ্যার একটি অ্যারে থাকে:

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

আমরা এর মতো প্রথম বিজোড় সংখ্যাটি খুঁজে পেতে পারি:

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

এটি alচ্ছিক পূর্ণসংখ্যার হিসাবে 4 ফেরত পাঠাবে, কারণ প্রথম বিজোড় সংখ্যা (9) সূচক চারে রয়েছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.