Do you want to pick up from where you left of?
Take me there

স্ট্রিং

স্ট্রিং, কার লিস্ট, গ্রাফীম ও কোড পয়েন্ট।

স্ট্রিং

এলিক্সির স্ট্রিং হলো কিছু বাইটের একটি সিকুয়েন্সমাত্র। একটা উদাহরণের সাহায্যে দেখা যাকঃ

iex> string = <<104,101,108,108,111>>
"hello"
iex> string <> <<0>>
<<104, 101, 108, 108, 111, 0>>

string এর সাথে বাইট 0 যোগ করার ফলে, IEx ওই স্ট্রিং কে বাইনারী হিসেবে দেখাবে, কারণ এটি এখন আর ভ্যালিড স্ট্রিং নেই। এই ট্রিকের মাধ্যমে আমরা যে কোন স্ট্রিং এর ভিতরের বাইট গুলো দেখতে পারি।

নোট- << >> সিনট্যাক্সের মাধ্যমে আমরা কম্পাইলারকে বলে দিচ্ছি যে এর ভেতরকার সদস্যরা বাইট।

কার লিস্ট

অভ্যন্তরীনভাবে, এলিক্সির স্ট্রিংসমূহ বাইটের সিকুয়েন্স হিসেবে ব্যবহৃত হয়, ক্যারেক্টার অ্যারে হিসেবে নয়। এলিক্সিরের আবার ক্যারেক্টার অ্যারে টাইপ রয়েছে। এলিক্সিরে স্ট্রিংকে ডাবল কোট ও ক্যারেক্টার লিস্টকে সিঙ্গেল কোট দিয়ে প্রকাশ করা হয়। এদের মাঝে পার্থক্য কি? কারলিস্টের প্রতিটা ভ্যালু হলো ইউনিকোড ক্যারেক্টার কোড পয়েন্ট যেখানে বাইনারীতে কোড পয়েন্ট গুলো UTF-8 এ এনকোড করা থাকে। চলুন দেখা যাকঃ

iex> 'hełło'
[104, 101, 322, 322, 111]
iex> "hełło" <> <<0>>
<<104, 101, 197, 130, 197, 130, 111, 0>>

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

গ্রাফীম ও কোড পয়েন্ট

কোড পয়েন্ট হল সাধারণ ইউনিকোড ক্যারেক্টার যা এক বা একাধিক বাইট দ্বারা প্রকাশিত (UTF-8 ভেদে)। US ASCII বহির্ভুত ক্যারেক্টাররা সবসময়েই একাধিক বাইট সমন্বিত হয়ে থাকে। যেমন ল্যাটিন ক্যারেক্টার যাদের টিল্ডা অথবা অ্যাক্সেন্ট চিহ্ন (á, ñ, è) রয়েছে তারা সাধারণত ২ বাইট, কিছু এশিয়ান ল্যাঙ্গুয়েজ এর সঙ্কেত ৩ অথবা ৪ বাইট হতে পারে। গ্রাফীম হল একাধিক কোড পয়েন্টের সমন্বয় যা একটি ক্যারেক্টার হিসেবে প্রকাশিত।

স্ট্রিং মডিউলে এদের সাথে কাজ করার ফাংশন রয়েছে- graphemes/1 আর codepoints/1 যার উদাহরণ নীচে দেয়া হয়েছে-

iex> string = "\u0061\u0301"
"á"

iex> String.codepoints string
["a", "́"]

iex> String.graphemes string
["á"]

স্ট্রিং ফাংশন

চলুন স্ট্রিং মডিউলের বহুল ব্যবহৃত কিছু গুরুত্বপূর্ণ ফাংশনের সাথে পরিচিত হই। এই অধ্যায়ে শুধু মাত্র কয়েকটি ফাংশনের বর্ণনা দেয়া হলো। অন্যান্য ফাংশন সম্পর্কে জানতে হলে স্ট্রিংয়ের অফিসিয়াল ডকুমেন্টেশান দেখুন।

length/1

স্ট্রিংয়ের গ্রাফীম সংখ্যা রিটার্ন করে

iex> String.length "Hello"
5

replace/3

নতুন একটি স্ট্রিং রিটার্ন করে যা একটি স্ট্রিংয়ের প্যাটার্নপ্রাপ্ত অংশকে আরেকটি স্ট্রিং দিয়ে রিপ্লেস করে।

iex> String.replace("Hello", "e", "a")
"Hallo"

duplicate/2

একটি স্ট্রিংকে n সংখ্যক বার রিপিট করে নতুন স্ট্রিং গঠন করে

iex> String.duplicate("Oh my ", 3)
"Oh my Oh my Oh my "

split/2

প্যাটার্ন অনুযায়ী একটি স্ট্রিংকে লিস্ট এ বিভাজিত করে

iex> String.split("Hello World", " ")
["Hello", "World"]

অনুশীলনী

আমরা স্ট্রিং ব্যবহারে সক্ষম এটা দেখতে চলুন একটি সহজ অনুশীলন দেখে নেই।

অ্যানাগ্রাম

A ও B পরস্পর অ্যানাগ্রাম হবে যদি এদেরকে পুনঃবিন্যস্ত করে একে অপরের সমান একটি বিন্যাস পাওয়া যায়। যেমন

আমরা যদি স্ট্রিং A কে পুনঃবিন্যাস করি তবে আমরা B পেতে পারি। উলটোটাও সম্ভব।

তাহলে আমরা কি করে একটি প্রোগ্রাম লিখতে পারি যা অ্যানাগ্রাম নির্ণয় করবে? সহজতম উপায় হল এদের গ্রাফীমকে বর্ণের ক্রমানুসারে বিন্যস্ত করা এবং দেখা যে তারা সমান কিনা। চেষ্টা করা যাক-

defmodule Anagram do
  def anagrams?(a, b) when is_binary(a) and is_binary(b) do
    sort_string(a) == sort_string(b)
  end

  def sort_string(string) do
    string
    |> String.downcase()
    |> String.graphemes()
    |> Enum.sort()
  end
end

anagrams?/2 একটু দেখি। আমরা প্রথমে চেক করছি যে এর প্যারামিটার বাইনারি কি না। এটি একটি এলিক্সির কোড স্টাইল যা নির্ণয় করে কোন প্যারামিটার স্ট্রিং কি না।

এরপর আমরা একটি ফাংশন ব্যবহার করছি যা স্ট্রিংগুলিকে বর্ণের ক্রমানুযায়ী সাজায়। প্রথমে এদেরকে ছোট হাতের অক্ষরে পরিণত করে অতঃপর String.graphemes দিয়ে গ্রাফীমগুলিকে আলাদা করেছি এবং সবশেষে Enum.sort এর মাধ্যমে বিন্যস্ত করে নিয়েছি।

IEx এ অউটপুট দেখে নেই-

iex> Anagram.anagrams?("Hello", "ohell")
true

iex> Anagram.anagrams?("María", "íMara")
true

iex> Anagram.anagrams?(3, 5)
** (FunctionClauseError) no function clause matching in Anagram.anagrams?/2

    The following arguments were given to Anagram.anagrams?/2:

        # 1
        3

        # 2
        5

    iex:11: Anagram.anagrams?/2

anagrams? এর শেষ কলে FunctionClauseError প্রদর্শিত হয়েছে কারণ ফাংশনের বর্ণনার সময়ে কোন প্যাটার্ন পাওয়া যায়নি যা কিনা বাইনারি ব্যতিরেকে কোন প্যারামিটার গ্রহণ করে। আমরা ঠিক তা-ই চেয়েছিলাম।

Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!