স্ট্রিং.আইডেক্স কীভাবে সুইফটে কাজ করে


108

আমি আমার পুরানো কিছু কোড এবং উত্তরগুলি সুইফট 3 এর সাথে আপডেট করছি কিন্তু যখন আমি সুইফ্ট স্ট্রিংস এবং সূচিপত্রের কাছে এলাম তখন জিনিসগুলি বোঝার জন্য ব্যথা হয়ে যায়।

বিশেষত আমি নিম্নলিখিতটি চেষ্টা করছিলাম:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5) // error

যেখানে দ্বিতীয় লাইনটি আমাকে নিম্নলিখিত ত্রুটি দিচ্ছে

'অ্যাডভান্সডবাই' অনুপলব্ধ: ক্যারেক্টারভিউ ইভেন্টে সূচকে উত্সাহিত করার জন্য এন পদক্ষেপের মাধ্যমে সূচককে অগ্রসর করতে 'ইনডেক্স (_: অফসেটবি :) :)' কল করুন।

আমি দেখি যে Stringনিম্নলিখিত পদ্ধতি আছে।

str.index(after: String.Index)
str.index(before: String.Index)
str.index(String.Index, offsetBy: String.IndexDistance)
str.index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)

এগুলি প্রথমে আমাকে সত্যিই বিভ্রান্ত করেছিল তাই আমি বুঝতে না পারছি তাদের সাথে খেলা শুরু করলাম। সেগুলি কীভাবে ব্যবহৃত হয় তা দেখানোর জন্য আমি নীচে একটি উত্তর যুক্ত করছি।

উত্তর:


280

এখানে চিত্র বর্ণনা লিখুন

নীচের সমস্ত উদাহরণ ব্যবহার করে

var str = "Hello, playground"

startIndex এবং endIndex

  • startIndex প্রথম চরিত্রের সূচক
  • endIndexশেষ চরিত্রের পরে সূচক হয়

উদাহরণ

// character
str[str.startIndex] // H
str[str.endIndex]   // error: after last character

// range
let range = str.startIndex..<str.endIndex
str[range]  // "Hello, playground"

সুইফট 4 এর একতরফা রেঞ্জের সাথে , পরিসীমাটি নিম্নলিখিত ফর্মগুলির মধ্যে একটিতে সরল করা যেতে পারে।

let range = str.startIndex...
let range = ..<str.endIndex

আমি স্পষ্টতার স্বার্থে অনুসরণের উদাহরণগুলিতে পূর্ণ ফর্মটি ব্যবহার করব, তবে পঠনযোগ্যতার জন্য আপনি সম্ভবত আপনার কোডে একতরফা রেঞ্জ ব্যবহার করতে চাইবেন।

after

হিসাবে: index(after: String.Index)

  • after প্রদত্ত সূচকের পরে সরাসরি চরিত্রের সূচককে বোঝায়।

উদাহরণ

// character
let index = str.index(after: str.startIndex)
str[index]  // "e"

// range
let range = str.index(after: str.startIndex)..<str.endIndex
str[range]  // "ello, playground"

before

হিসাবে: index(before: String.Index)

  • before প্রদত্ত সূচকের সরাসরি অক্ষরের সূচককে বোঝায়।

উদাহরণ

// character
let index = str.index(before: str.endIndex)
str[index]  // d

// range
let range = str.startIndex..<str.index(before: str.endIndex)
str[range]  // Hello, playgroun

offsetBy

হিসাবে: index(String.Index, offsetBy: String.IndexDistance)

  • offsetByমান ইতিবাচক বা নেতিবাচক এবং প্রদত্ত সূচি থেকে শুরু হতে পারে। যদিও এটি ধরণের String.IndexDistance, আপনি এটি একটি দিতে পারেন Int

উদাহরণ

// character
let index = str.index(str.startIndex, offsetBy: 7)
str[index]  // p

// range
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range]  // play

limitedBy

হিসাবে: index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)

  • limitedByনিশ্চিত করুন যে অফসেট সূচক সীমার বাইরে যেতে পারে না তৈরীর জন্য দরকারী। এটি একটি বাউন্ডিং সূচক। যেহেতু অফসেটের সীমা অতিক্রম করা সম্ভব, এই পদ্ধতিটি একটি anচ্ছিক প্রদান করে। nilসূচক সীমার বাইরে থাকলে এটি ফিরে আসে ।

উদাহরণ

// character
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
    str[index]  // p
}

যদি অফসেটের 77পরিবর্তে থাকত 7তবে ifবিবৃতিটি এড়িয়ে যায়।

স্ট্রিং.আইডেক্সের দরকার কেন?

এটা হবে অনেক একটি ব্যবহার করা আরো সহজ Intস্ট্রিং জন্য সূচি। যে কারণে আপনাকে String.Indexপ্রতিটি স্ট্রিংয়ের জন্য একটি নতুন তৈরি করতে হবে তা হ'ল সুইফ্টের অক্ষরগুলি হুডের নীচে সমস্ত একই দৈর্ঘ্য নয়। একটি একক সুইফ্ট চরিত্রটি এক, দুটি বা আরও বেশি ইউনিকোড কোড পয়েন্ট নিয়ে গঠিত হতে পারে। এইভাবে প্রতিটি অনন্য স্ট্রিংয়ের অবশ্যই তার অক্ষরগুলির সূচীগুলি গণনা করতে হবে।

এই জটিলতাটি কোনও ইনড ইনডেক্স এক্সটেনশনের পিছনে লুকিয়ে রাখা সম্ভবত, তবে আমি এটি করতে নারাজ। আসলে কী ঘটছে তা মনে করিয়ে দেওয়া ভাল।


18
কেন startIndex0 বাদে অন্য কিছু হবে ?
রোবো রোবক

15
@ রোবরোবোক: যেহেতু সুইফট ইউনিকোড অক্ষরগুলির সাথে কাজ করে যা "গ্রাফি ক্লাস্টার" দিয়ে তৈরি, তাই সুইফট সূচীগুলির অবস্থানগুলি উপস্থাপন করতে পূর্ণসংখ্যা ব্যবহার করে না। ধরা যাক আপনার প্রথম চরিত্রটি একটি é। এটা আসলে তৈরি করা হয় eপ্লাস একটি \u{301}ইউনিকোড উপস্থাপনা। আপনি যদি শূন্যের একটি সূচক ব্যবহার করেন তবে আপনি একটি eবা অ্যাকসেন্ট ("কবর") অক্ষর পাবেন, পুরো ক্লাস্টারটি তৈরি করবে না éstartIndexআপনি যে কোনও চরিত্রের জন্য পুরো গ্রাফি ক্লাস্টারটি পাবেন তা নিশ্চিত করে ব্যবহার করে ।
লেন

2
সুইফট ৪.০ এ প্রতিটি ইউনিকোড অক্ষরকে ১ দ্বারা গণনা করা হয়। যেমন: "👩‍💻" .কাউন্ট // এখন: 1, আগে: 2
সেলভা

3
String.Indexডামি স্ট্রিং তৈরি করা এবং এর .indexউপর পদ্ধতিটি ব্যবহার করা ছাড়া কীভাবে কোনও একটি পূর্ণসংখ্যা থেকে একটি তৈরি করে? আমি কিছু মিস করছি কিনা তা আমি জানি না, তবে দস্তাবেজগুলি কিছুই বলে না।
sudo

3
@ সুডো, String.Indexএকটি পূর্ণসংখ্যার সাথে একটি নির্মাণ করার সময় আপনাকে কিছুটা সতর্কতা অবলম্বন করতে হবে কারণ প্রতিটি সুইফ্ট Characterঅগত্যা আপনার পূর্ণসংখ্যার সাথে একই জিনিসটির সমান হয় না। এটি বলেছিল, আপনি একটি offsetByতৈরি করতে প্যারামিটারে একটি পূর্ণসংখ্যা পাস করতে পারেন String.Index। আপনার যদি না থাকে Stringতবে আপনি String.Indexএকটিটি নির্মাণ করতে পারবেন না (কারণ স্ট্রিংটিতে পূর্ববর্তী অক্ষরগুলি কী তা যদি সুইফট জানত তবে সূচকটি গণনা করতে পারে)। আপনি যদি স্ট্রিং পরিবর্তন করেন তবে আপনাকে অবশ্যই সূচিটি পুনরায় গণনা করতে হবে। আপনি String.Indexদুটি ভিন্ন স্ট্রিংয়ে একই ব্যবহার করতে পারবেন না ।
সুরগাচ

0
func change(string: inout String) {

    var character: Character = .normal

    enum Character {
        case space
        case newLine
        case normal
    }

    for i in stride(from: string.count - 1, through: 0, by: -1) {
        // first get index
        let index: String.Index?
        if i != 0 {
            index = string.index(after: string.index(string.startIndex, offsetBy: i - 1))
        } else {
            index = string.startIndex
        }

        if string[index!] == "\n" {

            if character != .normal {

                if character == .newLine {
                    string.remove(at: index!)
                } else if character == .space {
                    let number = string.index(after: string.index(string.startIndex, offsetBy: i))
                    if string[number] == " " {
                        string.remove(at: number)
                    }
                    character = .newLine
                }

            } else {
                character = .newLine
            }

        } else if string[index!] == " " {

            if character != .normal {

                string.remove(at: index!)

            } else {
                character = .space
            }

        } else {

            character = .normal

        }

    }

    // startIndex
    guard string.count > 0 else { return }
    if string[string.startIndex] == "\n" || string[string.startIndex] == " " {
        string.remove(at: string.startIndex)
    }

    // endIndex - here is a little more complicated!
    guard string.count > 0 else { return }
    let index = string.index(before: string.endIndex)
    if string[index] == "\n" || string[index] == " " {
        string.remove(at: index)
    }

}

-2

টেবিলভিউ কনট্রোলারের ভিতরে একটি ইউআইটিএক্সটেক্স ভিউ তৈরি করুন। আমি ফাংশনটি ব্যবহার করেছি: টেক্সটভিউডিডচেনজ এবং তারপরে রিটার্ন-কী-ইনপুট পরীক্ষা করে দেখলাম। তারপরে যদি এটি রিটার্ন-কী-ইনপুট সনাক্ত করে, রিটার্ন কীটির ইনপুট মুছুন এবং কীবোর্ড খারিজ করুন।

func textViewDidChange(_ textView: UITextView) {
    tableView.beginUpdates()
    if textView.text.contains("\n"){
        textView.text.remove(at: textView.text.index(before: textView.text.endIndex))
        textView.resignFirstResponder()
    }
    tableView.endUpdates()
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.