সুইফ্ট অ্যারে - একটি সূচক বিদ্যমান কিনা তা পরীক্ষা করুন


140

সুইফটে, কোনও মারাত্মক ত্রুটি নিক্ষেপ করা ছাড়াই একটি সূচকের কোনও অ্যারে উপস্থিত রয়েছে কিনা তা পরীক্ষা করার কোনও উপায় আছে কি?

আমি আশা করছিলাম যে আমি এরকম কিছু করতে পারি:

let arr: [String] = ["foo", "bar"]
let str: String? = arr[1]
if let str2 = arr[2] as String? {
    // this wouldn't run
    println(str2)
} else {
    // this would be run
}

তবে আমি পেয়েছি

মারাত্মক ত্রুটি: অ্যারে সূচি সীমার বাইরে

উত্তর:


442

সুইফটে একটি মার্জিত উপায়:

let isIndexValid = array.indices.contains(index)

10
বাস্তব জীবনে, এটি গুরুত্বপূর্ণ নয় তবে সময়-জটিলতা-ভিত্তিক এটি ব্যবহার করা আরও ভাল কি হবে না index < array.count?
funct7

2
আমি সত্যই বলেছি যে আপনি যে উদাহরণ দিয়েছেন তা কিছুটা সংশ্লেষিত, যেহেতু আমি কখনই নেতিবাচক সূচক মান রাখার অভিজ্ঞতা পাইনি, তবে যদি সত্যই এটি হওয়া উচিত হয় তবে দুটি সত্য / মিথ্যা চেক আরও ভাল হতে পারে: অর্থাত্ index >= 0 && index < array.countসবচেয়ে খারাপ ক্ষেত্রে পরিবর্তে এন তুলনা।
funct7

13
আপনি যদি ভাবেন যে গতির পার্থক্য কী, আমি এটি Xcode এর সরঞ্জামগুলি দিয়ে পরিমাপ করেছি এবং এটি नगणনীয়। gist.github.com/masonmark/a79bfa1204c957043687f4bdaef0c2ad
ম্যাসন

7
কেন এটি সঠিক তা সম্পর্কে কেবলমাত্র অন্য একটি বক্তব্য যুক্ত করতে: আপনি যদি কাজ করে যখন একই যুক্তি প্রয়োগ করেন ArraySliceতবে প্রথম সূচক 0 হবে না, সুতরাং index >= 0এটি করা যথেষ্ট পর্যাপ্ত চেক হবে না। .indicesপরিবর্তে যে কোনও ক্ষেত্রে কাজ করে।
DeFrenZ

2
আমি এর জন্য সুইফটকে ভালবাসি। এখানে আমার ব্যবহারের কেসটি রয়েছে: পরিষেবার জন্য জেএসওএন কাঠামো বিল্ডিংয়ের জন্য এটি করতে হয়েছিল: "অ্যাটেন্ডি 3": নাম.indices.contains (2)? নামগুলি [2]: ""
লি প্রবার্ট

64

প্রকারের প্রসার:

extension Collection {

    subscript(optional i: Index) -> Iterator.Element? {
        return self.indices.contains(i) ? self[i] : nil
    }

}

এটি ব্যবহার করে আপনি আপনার সূচকে optionচ্ছিক কীওয়ার্ড যুক্ত করার সময় একটি alচ্ছিক মান ফিরে পেতে পারেন যার অর্থ আপনার সূচক সীমার বাইরে থাকলেও আপনার প্রোগ্রামটি ক্রাশ হয় না। আপনার উদাহরণে:

let arr = ["foo", "bar"]
let str1 = arr[optional: 1] // --> str1 is now Optional("bar")
if let str2 = arr[optional: 2] {
    print(str2) // --> this still wouldn't run
} else {
    print("No string found at that index") // --> this would be printed
}

4
দুর্দান্ত উত্তর para optionalপরামিতি ব্যবহার করার সময় এটি সর্বাধিক গুরুত্বপূর্ণ । ধন্যবাদ!
জাকুব

2
আশ্চর্যতা: ডি আমার দিন বাঁচিয়েছেন।
কোডেটার্ড

2
এটি সুন্দর
জো গ্যালিন্ড

32

সূচি অ্যারের আকারের চেয়ে কম কিনা তা পরীক্ষা করে দেখুন:

if 2 < arr.count {
    ...
} else {
    ...
}

3
অ্যারের আকারটি অজানা থাকলে কী হবে?
নাথান ম্যাককাস্কলে

8
@ নাথানমিসকাস্কলে অ্যারে সর্বদা জানে যে এটিতে কতগুলি উপাদান রয়েছে তাই আকারটি অজানা হতে পারে
অ্যান্টোনিও

16
দুঃখিত আমি সেখানে ভাবছিলাম না। মর্নিং কফি তখনও রক্ত ​​প্রবাহে প্রবেশ করছিল।
নাথান ম্যাককাস্কলে

4
@ নাথান এমসি কাস্কলে কোনও উদ্বেগ নেই ... কখনও কখনও আমার সাথে এমনটি ঘটে, এমনকি বেশ কয়েকটি কফির পরেও ;-)
অ্যান্টোনিও

কিছু উপায়ে, এটি সেরা উত্তর, কারণ এটি ও (এন) এর পরিবর্তে ও (1) এ চলে।
স্কটিবিলেডস

12

কিছু এক্সটেনশন চিনি যুক্ত করুন:

extension Collection {
  subscript(safe index: Index) -> Iterator.Element? {
    guard indices.contains(index) else { return nil }
    return self[index]
  }
}

if let item = ["a", "b", "c", "d"][safe: 3] { print(item) }//Output: "d"
//or with guard:
guard let anotherItem = ["a", "b", "c", "d"][safe: 3] else {return}
print(anotherItem) // "d"

if letঅ্যারের সাথে একত্রে স্টাইল কোডিং করার সময় পঠনযোগ্যতা বাড়ায়


2
সত্যই, সর্বাধিক পঠনযোগ্যতা এবং স্পষ্টতার সাথে এটি করার সবচেয়ে দ্রুত উপায়
বারডোগ

1
@ বারডোগ এটিও পছন্দ করে আমি সাধারণত যে কোনও প্রকল্পে এটি সূগার হিসাবে যুক্ত করি। পাশাপাশি প্রহরী উদাহরণ যোগ করা হয়েছে। এইটির সাথে আসার জন্য সুইফট স্ল্যাক সম্প্রদায়ের কাছে ক্রেডিট।
নভেম্বর

ভাল সমাধান ... তবে আউটপুট "d" মুদ্রণ করবে উদাহরণস্বরূপ আপনি দিচ্ছেন ...
জয়ন্ত কাঁচাট

এটি সুইফট ভাষার অংশ হওয়া উচিত। সীমার বাইরে সূচক ইস্যুটি শূন্য মানের তুলনায় কম সমস্যাযুক্ত নয়। আমি এমনকি অনুরূপ সিনট্যাক্স ব্যবহার করার পরামর্শ দেব: সম্ভবত এর মতো কিছু: মাইআরাই [? 3]। মাইআরাই যদি alচ্ছিক হয় তবে আপনি কি আমারআরে পাবেন? [? 3]
অ্যান্ডি ওয়েইনস্টেইন

@ অ্যান্ডি ওয়াইনস্টাইন আপনার আপেলকে প্রস্তাব দেওয়া উচিত 💪
ইয়োনিস্ট e

7

অ্যারের আকার যাচাই করতে আপনি এটি নিরাপদ উপায়ে পুনর্লিখন করতে পারেন এবং একটি ত্রৈমাসিকীয় শর্তসাপেক্ষ ব্যবহার করতে পারেন:

if let str2 = (arr.count > 2 ? arr[2] : nil) as String?

1
অ্যান্টোনিও যা পরামর্শ দেয় তা অনেক বেশি স্বচ্ছ (এবং দক্ষ) যেখানে আপনার যদি ব্যবহারের জন্য খুব সহজেই উপলব্ধ মূল্য এবং সম্পূর্ণরূপে যদি তা মুছে ফেলার জন্য ত্রৈমাসিকের উপযুক্ত হবে তবে কেবলমাত্র একটি বিবৃতি ছেড়ে দিন।
ডেভিড বেরি

1
@ ডেভিড অ্যান্টোনিও যা পরামর্শ দেয় তার মূল কোডটিতে ifএকটি ifবিবৃতি না দিয়ে দুটি বিবৃতি প্রয়োজন । আমার কোডটি ifশর্তসাপেক্ষ অপারেটরের সাথে দ্বিতীয়টিকে প্রতিস্থাপন করে , আপনাকে elseদুটি পৃথক elseব্লক জোর করার পরিবর্তে একক রাখতে দেয়।
dasblinkenlight

1
আমি তার কোডে বিবৃতি দিলে দুটি দেখতে পাচ্ছি না, তার উপবৃত্তের জন্য str2 = এআরআর [1] রাখুন এবং এটি হয়ে গেছে। যদি আপনি ওপি প্রতিস্থাপন করেন তবে অ্যান্টোনিওর এর যদি বিবৃতিটি দিয়ে বিবৃতিটি লিখুন এবং অ্যাসাইনমেন্টটি ভিতরে স্থানান্তরিত করুন (বা না, যেহেতু কেবলমাত্র str2 এর একমাত্র ব্যবহার এটি প্রিন্ট করার দরকার নেই, কেবল প্রিন্টলনে dereferences ইনলাইন রেখে দিন mention যদি / অন্যথায় টেরিনারি অপারেটরটি কেবল একটি অস্পষ্ট (কারও কাছে :))। যদি অ্যারে। গণনা> 2, তারপরে আর [2] কখনই শূন্য হতে পারে না, তবে স্ট্রিংকে কেন এটি মানচিত্র করুন? ঠিক তাই আপনি বিবৃতি যদি অন্য আর আবেদন করতে পারেন।
ডেভিড বেরি

@ ডেভিড অ্যান্টোনিওর উত্তরটির "তত্ক্ষণিক if" শাখার মধ্যে ওপি-র প্রশ্ন থেকে সম্পূর্ণটি শেষ হবে, সুতরাং সেখানে দুটি নেস্টেড থাকবে if। আমি ওপিএস কোডটিকে একটি ছোট উদাহরণ হিসাবে দেখছি, তাই আমি ধরে নিচ্ছি যে তিনি এখনও একটি চান if। আমি আপনার সাথে একমত যে তাঁর উদাহরণে ifপ্রয়োজনীয় নয়। তবে আবারও পুরো বিবৃতিটি অর্থহীন, কারণ ওপি জানে যে অ্যারের যথেষ্ট দৈর্ঘ্য নেই এবং এর উপাদানগুলির কোনওটিই নেই nil, তাই সে এটি সরিয়ে ফেলতে পারে ifএবং কেবল এটির elseব্লক রাখতে পারে ।
dasblinkenlight

না এটা হবে না। অ্যান্টোনিও যদি ওপির আইফিকে প্রতিস্থাপন করে। যেহেতু অ্যারের প্রকারটি [স্ট্রিং] আপনি জানেন যে এটি কখনই শিল থাকতে পারে না, সুতরাং দৈর্ঘ্যের বাইরে কিছু পরীক্ষা করার দরকার নেই।
ডেভিড বেরি

7

সুইফট 4 এক্সটেনশন:

আমার জন্য আমি পদ্ধতির মতো পছন্দ করি।

// MARK: - Extension Collection

extension Collection {

    /// Get at index object
    ///
    /// - Parameter index: Index of object
    /// - Returns: Element at index or nil
    func get(at index: Index) -> Iterator.Element? {
        return self.indices.contains(index) ? self[index] : nil
    }
}

@ বেন্নো ক্রেসকে ধন্যবাদ


1

একটি অ্যারে সূচক বিদ্যমান কিনা তা জোর দিয়ে:

আপনি এক্সটেনশন চিনি যুক্ত করতে না চাইলে এই পদ্ধতিটি দুর্দান্ত:

let arr = [1,2,3]
if let fourthItem = (3 < arr.count ?  arr[3] : nil ) {
     Swift.print("fourthItem:  \(fourthItem)")
}else if let thirdItem = (2 < arr.count ?  arr[2] : nil) {
     Swift.print("thirdItem:  \(thirdItem)")
}
//Output: thirdItem: 3

1
extension Array {
    func isValidIndex(_ index : Int) -> Bool {
        return index < self.count
    }
}

let array = ["a","b","c","d"]

func testArrayIndex(_ index : Int) {

    guard array.isValidIndex(index) else {
        print("Handle array index Out of bounds here")
        return
    }

}

ইন্ডেক্সআউটআউটবাউন্ডস পরিচালনা করা আমার পক্ষে কাজ ।


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