স্

স্ট্রিং মধ্যে Julia

7টি অনুশীলনী

স্ট্রিং সম্পর্কে

Julia-তে একটি String হলো ক্যারেক্টারের একটি ক্রমবদ্ধ সিকোয়েন্স। ম্যানুয়াল-এ বলা হয়েছে: "অবশ্যই, আসল সমস্যা শুরু হয় যখন কেউ জিজ্ঞেস করে ক্যারেক্টার আসলে কী।"

এই জটিলতার অনেকটাই Chars কনসেপ্টে আরও বিস্তারিতভাবে আলোচনা করা হবে, তবে সংক্ষেপে:

  • Julia-তে সব স্ট্রিং Unicode।
  • যে স্ট্রিংগুলো ASCII-ও (ইংরেজি বর্ণ A থেকে Z বড় ও ছোট হাতের, অঙ্ক এবং কয়েকটি যতিচিহ্ন ক্যারেক্টার) সেগুলো নিয়ে কাজ করা সহজ।
  • বিশ্বের বাকি বেশিরভাগ লিখনপদ্ধতি নিয়ে কাজ করা সম্ভব, কিন্তু বেশি সতর্কতা দরকার।

স্ট্রিং লিটারাল

সাধারণভাবে স্ট্রিংগুলো ডাবল কোট " "-এর মধ্যে রাখা হয়। সিঙ্গেল কোট ' ' শুধু Chars-এর জন্য ব্যবহৃত হয়।

তিনটি ডাবল কোট """ """-ও ব্যবহার করা যায়, যা স্ট্রিংয়ের ভেতরে " ব্যবহার করতে দেয় এস্কেপিং ছাড়াই। আরও গুরুত্বপূর্ণ, মাল্টিলাইন স্ট্রিং থেকে অবাঞ্ছিত অতিরিক্ত ইন্ডেন্টেশন বাদ দেওয়া হয়।

julia> """
       Multiline
       String
       """
"Multiline\nString\n"

ক্যারেক্টার এস্কেপ করা

C থেকে শুরু করে বেশিরভাগ ভাষার মতো, Julia এস্কেপিংয়ের জন্য ব্যাকস্ল্যাশ \ ব্যবহার করে:

  1. নন-প্রিন্টিং ক্যারেক্টার লেখার জন্য, যেমন আগের উদাহরণের নিউলাইন \n।
  2. এমন ক্যারেক্টার রক্ষা করার জন্য যেগুলোর অন্যথায় বিশেষ অর্থ থাকত, যেমন \$ (নিচে দেখুন)।

ইটারেশন

একটি স্ট্রিং হলো একটি ইটারেবল কালেকশন, তাই ক্যারেক্টারের ভেক্টরে রূপান্তর করার কোনো প্রয়োজন ছাড়াই for ... in লুপ কাজ করবে।

julia> s = "Julia"
"Julia"

# admittedly, this is a silly example
julia> for c in s; print(c, "; "); end
J; u; l; i; a; 

এভাবে ইটারেট করলে সুবিধা হলো Julia ক্যারেক্টারের সীমানা সঠিকভাবে সামলাবে, এমনকি নন-ASCII স্ট্রিংয়ের ক্ষেত্রেও। এর গুরুত্ব পরের অংশে আরও স্পষ্ট হবে।

ইনডেক্সিং

নীতিগতভাবে, স্ট্রিংগুলোকে ভেক্টরের মতোই ইনডেক্স করা যায়:

julia> s[1], s[5]
('J', 'a')

এটি "Julia"-র মতো একটি ASCII স্ট্রিংয়ের জন্য স্পষ্টভাবে কাজ করে, কিন্তু এতে বিশ্বের বেশিরভাগ ভাষা উপেক্ষিত হয়।

প্রায় ১৫ শতাব্দী আগে প্রাচীন ইংরেজিতে লেখা Beowulf-এর একটি ক্যারেক্টার বিবেচনা করুন।

"Hrōðgār" স্পষ্টতই ৭টি ক্যারেক্টার, কিন্তু তাদের সবগুলো ASCII নয়।

julia> king = "Hrōðgār"
"Hrōðgār"

julia> length(king)
7

julia> isascii(king)
false

# collect() converts to a Char vector:
julia> collect(king)
7-element Vector{Char}:
 'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)
 'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)
 'ō': Unicode U+014D (category Ll: Letter, lowercase)
 'ð': Unicode U+00F0 (category Ll: Letter, lowercase)
 'g': ASCII/Unicode U+0067 (category Ll: Letter, lowercase)
 'ā': Unicode U+0101 (category Ll: Letter, lowercase)
 'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)

এভাবে একটি স্ট্রিংয়ে ইনডেক্স করা শুরুতে ভালোই চলে, কিন্তু কোনো এক পর্যায়ে ভেঙে পড়ে:

julia> king[3]
'ō': Unicode U+014D (category Ll: Letter, lowercase)

julia> king[4]
ERROR: StringIndexError: invalid index [4], valid nearby indices [3]=>'ō', [5]=>'ð'

সমস্যা হলো এভাবে ইনডেক্স করলে বাইট গোনা হয়, যেগুলোর নন-ASCII স্ট্রিংয়ে ক্যারেক্টারের সাথে ১:১ সম্পর্ক থাকে না। একটি Unicode/UTF-8 ক্যারেক্টার উপস্থাপন করতে ৪টি পর্যন্ত বাইট লাগতে পারে, এবং Chars কনসেপ্টে এটি আরও বিশদে আলোচনা করা হবে।

স্ট্রিং তৈরি করা

কনক্যাটেনেশন

অনেক ভাষা স্ট্রিং কনক্যাটেনেশন অপারেটরের জন্য + ব্যবহার করে, কিন্তু Julia নয়। অন্তত এরর মেসেজটি সহায়ক।

julia> "s1 " + "s2"
ERROR: MethodError: no method matching +(::String, ::String)
The function `+` exists, but no method is defined for this combination of argument types.
String concatenation is performed with * 

julia> "s1 " * "s2"
"s1 s2"

string() ফাংশন যেকোনো সংখ্যক স্ট্রিং কনক্যাটেনেট করবে।

julia> string("lots ", "of ", "bits")
"lots of bits"

join() ফাংশনও একই কাজ করবে, এবং স্ট্রিংয়ের একটি ভেক্টর নিয়ে সেগুলোকে একটি নির্দিষ্ট সেপারেটর দিয়ে কনক্যাটেনেট করবে (ডিফল্ট "")।

julia> join(["lots", "of", "bits"], "_")
"lots_of_bits"

মনে রাখবেন, স্ট্রিং ইমিউটেবল, আর কনক্যাটেনেশনে কপি করা জড়িত থাকে। তাই লুপের ভেতরে বারবার কনক্যাটেনেশন করলে অদক্ষ হয়; বরং টুকরোগুলো একটি ভেক্টরে জমিয়ে শেষে সবগুলোকে join করা ভালো।

পুনরাবৃত্তি

সহজ:

julia> repeat("Abc", 5)
"AbcAbcAbcAbcAbc"

ইন্টারপোলেশন

অনেক ভাষায়ই স্ট্রিংয়ের ভেতরে হিসাব করা মান বসানোর উপায় আছে, যদিও কোন সিনট্যাক্সটি সবচেয়ে ভালো তা নিয়ে চরম মতভেদ রয়েছে।

Julia-তে ইন্টারপোলেটেড মানের আগে $ থাকে।

julia> myvar = 42
42

julia> "myvar evaluates to $myvar"
"myvar evaluates to 42"

julia> r = 5.3
5.3

julia> "A circle of radius $r has area $(π * r^2)"
"A circle of radius 5.3 has area 88.24733763933729"

যখন বন্ধনী বাদ দিলে অস্পষ্টতা তৈরি হবে তখন বন্ধনী আবশ্যক, কিন্তু একটি আইডেন্টিফায়ারের পরে হোয়াইটস্পেস থাকলে তা ঐচ্ছিক।

স্ট্রিংয়ে একটি $ রাখতে হলে সেটিকে \$ হিসেবে এস্কেপ করুন।

মনে রাখবেন, ইন্টারপোলেশনে বর্তমানে ফরম্যাটিং সমর্থিত নয়, যেমন কত দশমিক স্থান দেখানো হবে তা নির্ধারণ করা।

বিকল্প উপায়গুলো হলো:

  • হিসাবটি একটি round() ফাংশনের ভেতরে রেখে দিন।
  • Exercism টেস্ট রানারের বাইরে, PyFormattedStrings প্যাকেজটি Python f-strings-এর অনুকরণ করে।
  • @sprintf() ম্যাক্রোটি নিচে বর্ণনা করা হয়েছে।

@sprintf()

স্ট্রিং অ্যাসেম্বলির আরও সূক্ষ্ম নিয়ন্ত্রণের জন্য, Julia C থেকে sprintf ফাংশনটি নকল করেছে (এবং পরবর্তী বেশ কয়েকটি ভাষাও: উইকিপিডিয়া তালিকা প্রায় ৩০টি ভাষার তালিকা দেয়)।

Julia-তে এটি Printf মডিউলের ভেতরে একটি macro হিসেবে বাস্তবায়িত, তাই @ প্রিফিক্স।

julia> using Printf

julia> r = 5.3
5.3

julia> @sprintf("A circle of radius %.1f has area %.2f", r, π * r^2)
"A circle of radius 5.3 has area 88.25"

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

সহজতার জন্য, এই অংশে এমন ফাংশনগুলোর উপর জোর দেওয়া হবে যেগুলো একটি নতুন স্ট্রিং রিটার্ন করে এবং ইনপুট অপরিবর্তিত রাখে। অনেকগুলোর একটি সমতুল্য রূপ আছে, যার নামের শেষে ! থাকে, যা ইনপুটকে জায়গাতেই পরিবর্তন করে।

দৈর্ঘ্য

একটি স্ট্রিং কত লম্বা? কখনও কখনও তা নির্ভর করে আপনি কীভাবে গুনছেন তার উপর।

সহজ ক্ষেত্র হলো ASCII স্ট্রিং, যেখানে প্রতিটি ক্যারেক্টার ১ বাইট জায়গা নেয়।

julia> string_asc = "Julia"
"Julia"

julia> length(string_asc)
5

julia> sizeof(string_asc)
5

length() ফাংশন ক্যারেক্টার-এর সংখ্যা রিটার্ন করে, আর sizeof() ফাংশন বাইট-এর সংখ্যা।

অন্য ক্যারেক্টার সেটের ক্ষেত্রে এই পার্থক্য গুরুত্বপূর্ণ হয়ে ওঠে:

julia> king = "Hrōðgār"
"Hrōðgār"

julia> length(king)
7

julia> sizeof(king)
10

ভাগ করা

প্রোগ্রামিংয়ে একটি কমন অপারেশন হলো একটি লম্বা স্ট্রিং নিয়ে সেটিকে এক বা একাধিক ক্যারেক্টারের সেপারেটর স্ট্রিংয়ের ভিত্তিতে টুকরো টুকরো ভাগ করা।

সাধারণভাবে, আমরা split() ফাংশনটি ব্যবহার করি। সেপারেটর ডিফল্টভাবে (যেকোনো) হোয়াইটস্পেস, তবে অন্য সেপারেটরও নির্দিষ্ট করা যায়।

julia> split("my little string")
3-element Vector{SubString{String}}:
 "my"
 "little"
 "string"

julia> split("My_snake_case_string", "_")
4-element Vector{SubString{String}}:
 "My"
 "snake"
 "case"
 "string"

এই উদাহরণগুলো একটি স্ট্রিংকে ছোট ছোট স্ট্রিং-এ ভাগ করে। একটি স্ট্রিংকে ক্যারেক্টার-এ ভাগ করা ভিন্ন অপারেশন।

julia> collect("input string")
12-element Vector{Char}:
 'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)
 'n': ASCII/Unicode U+006E (category Ll: Letter, lowercase)
 'p': ASCII/Unicode U+0070 (category Ll: Letter, lowercase)
 'u': ASCII/Unicode U+0075 (category Ll: Letter, lowercase)
 't': ASCII/Unicode U+0074 (category Ll: Letter, lowercase)
 ' ': ASCII/Unicode U+0020 (category Zs: Separator, space)
 's': ASCII/Unicode U+0073 (category Ll: Letter, lowercase)
 't': ASCII/Unicode U+0074 (category Ll: Letter, lowercase)
 'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)
 'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)
 'n': ASCII/Unicode U+006E (category Ll: Letter, lowercase)
 'g': ASCII/Unicode U+0067 (category Ll: Letter, lowercase)

খোঁজা ও প্রতিস্থাপন

একটি স্ট্রিংয়ে নির্দিষ্ট কোনো সাবস্ট্রিং আছে কি? অদ্ভুতভাবে, এটি পরীক্ষা করার দুটি ফাংশন আছে: occursin() এবং contains() শুধু তাদের আর্গুমেন্টের ক্রমে আলাদা।

julia> needle = "Julia"
"Julia"

julia> haystack = "Python, Julia and R"
"Python, Julia and R"

julia> occursin(needle, haystack)
true

julia> contains(haystack, needle)
true

অবস্থান সম্পর্কে আরও নির্দিষ্ট হতে:

julia> startswith(haystack, "Python")
true

julia> endswith(haystack, "Python")
false

একটি সাবস্ট্রিংয়ের start:end ইনডেক্স পেতে, আমাদের কয়েকটি ফাংশন আছে:

julia> findfirst(needle, haystack)
9:13

সাবস্ট্রিং প্রতিস্থাপন করতে, x => y সিনট্যাক্স ব্যবহার করে পরিবর্তনগুলো তালিকাভুক্ত করুন।

julia> replace("abc", "a"=>"b", "b"=>"c", "c"=>"a")
"bca"

Julia 1.7 থেকে, replace ফাংশন যেকোনো সংখ্যক পরিবর্তন নিতে পারে, এই নিশ্চয়তা নিয়ে যে প্রতিস্থাপনের সময় কোনো ক্যারেক্টার একবারের বেশি পরিবর্তিত হবে না।

x => y সিনট্যাক্সকে pair বলা হয়, যা Julia-তে একটি গুরুত্বপূর্ণ টাইপ, এবং Dicts and Pairs কনসেপ্টে আরও বিস্তারিতভাবে আলোচনা করা হয়েছে।

নোট: সহজতার জন্য, উপরের সব উদাহরণে স্ট্রিং লিটারাল ব্যবহার করা হয়েছে। অনেক ফাংশন আরও সাধারণ, এবং Regular Expressions-এর সাথেও কাজ করবে। আমরা পরের একটি কনসেপ্টে এটিতে ফিরে আসব।

হোয়াইটস্পেস

আমাদের প্রায়ই একটি স্ট্রিং থেকে শুরু এবং/অথবা শেষের হোয়াইটস্পেস সরাতে হয়।

এর জন্য ফাংশনগুলো হলো lstrip() (বাম), rstrip() (ডান), strip() (উভয়)।

julia> strip("\n\t  useful_bit\n\n")
"useful_bit"

কেস পরিবর্তন

এই ফাংশনগুলোর নামগুলো প্রায় স্ব-ব্যাখ্যাত্মক:

julia> s = repeat("aBcD ", 5)
"aBcD aBcD aBcD aBcD aBcD "

julia> uppercase(s)
"ABCD ABCD ABCD ABCD ABCD "

julia> lowercase(s)
"abcd abcd abcd abcd abcd "

julia> titlecase(s)  # Initial letter of each word uppercase
"Abcd Abcd Abcd Abcd Abcd "

পার্সিং

সংখ্যা এবং তাদের স্ট্রিং উপস্থাপনার মধ্যে পারস্পরিক রূপান্তর প্রায়ই উপকারী।

সংখ্যা থেকে স্ট্রিং করা সহজ, তবে ডিফল্ট ১০ ছাড়া অন্য কোনো বেসের জন্য একটি অতিরিক্ত প্যারামিটার দরকার:

julia> string(42)
"42"

julia> string(42, base=16)
"2a"

julia> string(42, base=2)
"101010"

স্ট্রিং পার্স করে একটি সাংখ্যিক মান পেতে একটু বেশি জটিল, এবং ভুলের সম্ভাবনাও বেশি। লক্ষ্য সাংখ্যিক টাইপ উল্লেখ করা বাধ্যতামূলক। বেস উল্লেখ করা ঐচ্ছিক এবং ডিফল্টভাবে ১০।

julia> parse(Int, "42")
42

julia> parse(Float64, "42")
42.0

julia> parse(Int, "42?")
ERROR: ArgumentError: invalid base 10 digit '?' in "42?"

julia> parse(Int, "42 ")  # whitespace may be tolerated
42

বিশেষ স্ট্রিং

কখনও কখনও স্ট্রিংয়ের ভেতরে স্বাভাবিক ইন্টারপোলেশন এবং এস্কেপিং বন্ধ করা কাজে লাগে। এর জন্য, শুরুর কোটের আগে raw বসান।

julia> x = 10
10

julia> "x = $x if we use \$ for interpolation"
"x = 10 if we use \$ for interpolation"

julia> raw"x = $x if we use \$ for interpolation"
"x = \$x if we use \\\$ for interpolation"

রেগুলার এক্সপ্রেশনের নিজস্ব জটিল সিনট্যাক্স আছে, এবং Julia দুটি সহায়ক স্ট্রিং টাইপ দেয়: Regex-এর জন্য r" " এবং ক্যাপচার করা টুকরো নিয়ে কাজ করার জন্য s" "।

আরও নানা বিশেষ স্ট্রিং Exercism-ধাঁচের প্রোগ্রামিংয়ে কম দেখা যায়, যদিও লাইব্রেরি তৈরিতে ব্যাপকভাবে ব্যবহৃত হয়।

  • সেমান্টিক ভার্সন স্ট্রিং v"x.y.z" সফটওয়্যার রিলিজের major.minor.patch নম্বরিং সামলায়।
  • বাইট অ্যারে লিটারাল b" " Unicode ক্যারেক্টার সীমানা এড়িয়ে বাইট স্তরে কাজ করে।
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি নতুন একটি উইন্ডো বা ট্যাবে খুলবে

স্ট্রিং শিখুন

অনুশীলন লক করা আছে

স্ট্রিং অনুশীলন করতে আরও 2টি অনুশীলনী আনলক করুন