Pairs and Dicts কনসেপ্টে Julia-র ডিকশনারি টাইপের মূল বিষয়গুলো নিয়ে আলোচনা করা হয়েছে।
Dict যেহেতু একটি গুরুত্বপূর্ণ ও বহুল ব্যবহৃত কালেকশন টাইপ, তাই এগুলো নিয়ে কাজ করার জন্য অনেক ফাংশনও রয়েছে।
কোনো এন্ট্রি বের করার সবচেয়ে সহজ উপায় হলো কী (key) দিয়ে খোঁজা (যেমনটা অনেক ভাষাতেই হয়)। তবে যে কী (key) নেই, সেটি চাইলে KeyError হয়।
julia> d = Dict(i => ('a':'c')[i] for i in 1:3)
Dict{Int64, Char} with 3 entries:
2 => 'b'
3 => 'c'
1 => 'a'
julia> d[2]
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
# missing key
julia> d[4]
ERROR: KeyError: key 4 not found
এন্ট্রি বের করার আগে আমরা যাচাই করে নিতে পারি যে কী (key)-টি আছে কি না (haskey(d, 4) জাতীয় কিছু দিয়ে), তবে অনুপস্থিত কী (key)-গুলোর জন্য সরাসরি একটি ডিফল্ট মান পেয়ে যাওয়াটাও কাজে লাগতে পারে।
এর জন্যই আছে get() ফাংশন আর তার পরিবর্তনশীল রূপ get!()। এদের মধ্যে পার্থক্য হলো, একটি "অনুপস্থিত" কী (key) Dict-এ যোগ হয় কি না।
julia> get(d, 4, '!')
'!': ASCII/Unicode U+0021 (category Po: Punctuation, other)
# get() leaves Dict unchanged
julia> d
Dict{Int64, Char} with 3 entries:
2 => 'b'
3 => 'c'
1 => 'a'
julia> get!(d, 4, '!')
'!': ASCII/Unicode U+0021 (category Po: Punctuation, other)
# get!() adds new key to Dict
julia> d
Dict{Int64, Char} with 4 entries:
4 => '!'
2 => 'b'
3 => 'c'
1 => 'a'
আগের কনসেপ্টে আমরা দেখেছি, delete!() কী (key) দিয়ে কোনো এন্ট্রি মুছে ফেলে। মানটি একসাথে বের করে আনার কাজে pop!() ফাংশনটি এর সঙ্গে মিলিয়ে ব্যবহার করা যায়।
julia> d
Dict{Int64, Char} with 4 entries:
4 => '!'
2 => 'b'
3 => 'c'
1 => 'a'
# popped value is returned
julia> pop!(d, 3)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
# Dict is shrunk
julia> d
Dict{Int64, Char} with 3 entries:
4 => '!'
2 => 'b'
1 => 'a'
একটি Dict-এর উপর ইটারেশন করলে ডিফল্টভাবে key => value জোড়া পাওয়া যায়। এই অংশগুলো স্বাভাবিক .first ও .second নাম দিয়ে পাওয়া যায়।
# d is from the previous example
julia> [(kv.first, kv.second) for kv in d]
3-element Vector{Tuple{Int64, Char}}:
(4, '!')
(2, 'b')
(1, 'a')
অনেক সময় আমরা শুধু কী (key)-গুলো বা শুধু ভ্যালুগুলো ব্যবহার করতে চাই, যা করা সহজ।
julia> [k for k in keys(d)]
3-element Vector{Int64}:
4
2
1
julia> [v for v in values(d)]
3-element Vector{Char}:
'!': ASCII/Unicode U+0021 (category Po: Punctuation, other)
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
দুটি Dict একসাথে করা কাজে লাগতে পারে, তবে একাধিক ইনপুটে থাকা কী (key)-গুলোর ক্ষেত্রে আমরা কী করতে চাই সেটি স্পষ্ট থাকা দরকার।
merge() ও merge!() ফাংশন যত খুশি সংখ্যক Dict দিলেও সেগুলোকে বাম থেকে ডানে ক্রমানুসারে একসাথে করে।
আগে থেকে থাকা কী (key)-গুলোর মান কেবল ওভাররাইট হয়ে যায়, তাই সবচেয়ে ডানের Dict-টাই "জিতে যায়"।
julia> d3 = Dict("color" => "red", "shape" => "circle")
Dict{String, String} with 2 entries:
"shape" => "circle"
"color" => "red"
julia> d4 = Dict("color" => "blue", "coords" => (3, 2))
Dict{String, Any} with 2 entries:
"color" => "blue"
"coords" => (3, 2)
# color from d3 is lost
julia> merge(d3, d4)
Dict{String, Any} with 3 entries:
"shape" => "circle"
"color" => "blue"
"coords" => (3, 2)
mergewith() ও mergewith!() ফাংশনে প্রথম আর্গুমেন্ট হিসেবে একটি ফাংশন দিতে পারি, যেটি ঠিক করে দেয় একই কী (key) বারবার এলে সেগুলো কীভাবে মার্জ হবে। যোগ করা এর একটি সহজ উদাহরণ।
julia> d5 = Dict("color" => "red", "area" => 3)
Dict{String, Any} with 2 entries:
"area" => 3
"color" => "red"
julia> d6 = Dict("shape" => "circle", "area" => 5)
Dict{String, Any} with 2 entries:
"shape" => "circle"
"area" => 5
# area values are added, not overwritten
julia> mergewith(+, d5, d6)
Dict{String, Any} with 3 entries:
"shape" => "circle"
"area" => 8
"color" => "red"
লক্ষ করুন, mergewith ফাংশনগুলো হায়ার অর্ডার ফাংশন কাজে লাগানোর একটি ভালো উদাহরণ।
Mecha Munch™, একটি মুদি কেনাকাটার অটোমেশন কোম্পানি, সদ্য আপনাকে তাদের অর্ডারিং অ্যাপে কাজ করার জন্য নিয়োগ দিয়েছে। আপনার দলের দায়িত্ব একটি MVP (ন্যূনতম কার্যকর পণ্য) বানানো, যা শপিং কার্টের সব মৌলিক কাজ সামলাবে এবং ব্যবহারকারীদের তাদের মুদি অর্ডার যোগ, বাদ দেওয়া আর সাজানোর সুবিধা দেবে। ভাগ্যক্রমে, টাকা-পয়সা আর চেক-আউটের সব কাজ অন্য একটি দল দেখছে!
MVP-তে ব্যবহারকারীকে তার শপিং কার্টে আইটেম যোগ করার সুবিধা থাকা উচিত। এটি একসাথে একটি আইটেম বা একাধিক আইটেম হতে পারে। যেহেতু এটি একটি MVP, আইটেমের পরিমাণ বোঝানো হয় পুনরাবৃত্তি দিয়ে। কোনো ব্যবহারকারী ২টি Orange যোগ করতে চাইলে ইনপুট ইটারেবলে 'Oranges' দুবার থাকবে। ব্যবহারকারীর কার্টে আইটেমটি আগে থেকেই থাকলে কার্টের পরিমাণ ১ বাড়িয়ে দিতে হবে। আইটেমটি কার্টে নতুন হলে সেটি ১ পরিমাণে যোগ করতে হবে।
add_items!(<cart>, <items>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে একটি কার্ট ডিকশনারি এবং যোগ করার জন্য আইটেমের একটি ইটারেবল নেয়।
এটি ব্যবহারকারীর জন্য আপডেট করা শপিং কার্ট ডিকশনারি রিটার্ন করবে।
julia> additems!(Dict("Banana" => 3, "Apple" => 2, "Orange" => 1),
("Apple", "Apple", "Orange", "Apple", "Banana"))
Dict{String, Int64} with 3 entries:
"Apple" => 5
"Orange" => 2
"Banana" => 4
julia> additems!(Dict("Banana" => 3, "Apple" => 2, "Orange" => 1),
["Banana", "Orange", "Blueberries", "Banana"])
Dict{String, Int64} with 4 entries:
"Blueberries" => 1
"Apple" => 2
"Orange" => 2
"Banana" => 5
অ্যাপটিতে একটি "আইডিয়া" সেকশন আছে, যা নানা রকম রান্নার তৈরি রেসিপিতে ভরা। ব্যবহারকারী এই রেসিপিগুলোর যেকোনো একটি বেছে নিলে তার সব উপকরণ স্বয়ংক্রিয়ভাবে শপিং কার্টে যোগ হয়ে যাবে। প্রজেক্ট ম্যানেজার আপনাকে এই "আইডিয়া" রেসিপিগুলো সম্পাদনা করার একটি উপায় বানাতে বলেছেন, কারণ কনটেন্ট টিম উপকরণ আর পরিমাণ বদলাতেই থাকে।
update_recipes!(<ideas>, <updates>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে একটি "আইডিয়া" ডিকশনারি এবং রেসিপি আপডেটের একটি ডিকশনারি নেয়।
ফাংশনটি আপডেট করা "আইডিয়া" ডিকশনারি রিটার্ন করবে।
julia>update_recipes!(
Dict("Banana Bread" => Dict("Banana" => 1, "Apple" => 1, "Walnuts" => 1, "Flour" => 1, "Eggs" => 2, "Butter" => 1),
"Raspberry Pie" => Dict("Raspberry" => 1, "Orange" => 1, "Pie Crust" => 1, "Cream Custard" => 1)),
Dict("Banana Bread" => Dict("Banana" => 4, "Walnuts" => 2, "Flour" => 1, "Butter" => 1, "Milk" => 2, "Eggs" => 3))
)
Dict{String, Dict{String, Int64}} with 2 entries:
"Raspberry Pie" => Dict("Cream Custard"=>1, "Raspberry"=>1, "Orange"=>1, "Pie Crust"=>1)
"Banana Bread" => Dict("Eggs"=>3, "Flour"=>1, "Milk"=>2, "Butter"=>1, "Walnuts"=>2, "Banana"=>4)
julia> update_recipes!(
Dict("Banana Bread" => Dict("Banana" => 1, "Apple" => 1, "Walnuts" => 1, "Flour" => 1, "Eggs" => 2, "Butter" => 1),
"Raspberry Pie" => Dict("Raspberry" => 1, "Orange" => 1, "Pie Crust" => 1, "Cream Custard" => 1),
"Pasta Primavera" => Dict("Eggs" => 1, "Carrots" => 1, "Spinach" => 2, "Tomatoes" => 3, "Parmesan" => 2, "Milk" => 1, "Onion" => 1)),
Dict("Raspberry Pie" => Dict("Raspberry" => 3, "Orange" => 1, "Pie Crust" => 1, "Cream Custard" => 1, "Whipped Cream" => 2),
"Pasta Primavera" => Dict("Eggs" => 1, "Mixed Veggies" => 2, "Parmesan" => 2, "Milk" => 1, "Spinach" => 1, "Bread Crumbs" => 1),
"Blueberry Crumble" => Dict("Blueberries" => 2, "Whipped Creme" => 2, "Granola Topping" => 2, "Yogurt" => 3))
)
Dict{String, Dict{String, Int64}} with 4 entries:
"Raspberry Pie" => Dict("Raspberry"=>3, "Orange"=>1, "Pie Crust"=>1, "Cream Custard"=>1, "Whipped Cream"=>2)
"Pasta Primavera" => Dict("Eggs"=>1, "Mixed Veggies"=>2, "Parmesan"=>2, "Milk"=>1, "Spinach"=>1, "Bread Crumbs"=>1)
"Blueberry Crumble" => Dict("Blueberries"=>2, "Whipped Creme"=>2, "Granola Topping"=>2, "Yogurt"=>3)
"Banana Bread" => Dict("Banana"=>1, "Apple"=>1, "Walnuts"=>1, "Flour"=>1, "Eggs"=>2, "Butter"=>1)
অ্যাপটিকে একটি নির্দিষ্ট ব্যবহারকারীর কার্ট ফুলফিলমেন্টের জন্য দোকানে পাঠাতে হবে। তবে দোকানের শপারদের একটি ইউনিক আইল কোড দেখে জানতে হবে কোন আইটেম কোথায় পাওয়া যাবে। "ফুলফিলমেন্ট কার্ট"-টি আইটেমগুলোর আইল কোডের ক্রম অনুযায়ী সাজানো দরকার, যাতে শপাররা আরও দক্ষভাবে কাজ করতে পারেন।
send_to_store(<cart>, <aislecodes>) ফাংশনটি তৈরি করুন, যা একটি ব্যবহারকারীর শপিং কার্ট এবং দোকানের আইল নম্বরসহ একটি ডিকশনারি নেয়।
ফাংশনটি একটি সম্মিলিত "ফুলফিলমেন্ট কার্ট" রিটার্ন করবে, যেখানে ক্রেতা যে প্রতিটি আইটেম অর্ডার করছেন তার জন্য aislecode => quantity জোড়া থাকবে।
আইটেমগুলো তাদের আইল কোডের ক্রম অনুযায়ী থাকবে।
julia> cart = Dict("Orange" => 1, "Milk" => 2, "Banana" => 3, "Apple" => 2, "Chocolate" => 2);
julia> aislecodes = Dict("Orange" => 2.4, "Milk" => 3.3, "Banana" => 2.6, "Apple" => 2.2, "Chocolate" => 5.7);
julia> send_to_store(cart, aislecodes)
5-element Vector{Pair{Float64, Int64}}:
2.2 => 2
2.4 => 1
2.6 => 3
3.3 => 2
5.7 => 2
অ্যাপ শুধু অনবরত ক্রেতার অর্ডার পাঠিয়ে যেতে পারে না। একসময় দোকানের নানা পণ্য ফুরিয়ে যাবে। তাই ব্যবহারকারী যখনই তার অর্ডার দোকানে পাঠাবে, আপনার অ্যাপের MVP-কে দোকানের ইনভেন্টরি আপডেট করতে হবে। নাহলে ক্রেতারা এমন পণ্য অর্ডার করবেন যা আসলে মজুত নেই।
update_store_inventory!(<inventory>, <cart>) ফাংশনটি তৈরি করুন, যা একটি cart এবং একটি inventory নেয়।
ফাংশনটি "কার্টে" যত সংখ্যায় অর্ডার করা আছে সেই পরিমাণ দোকানের ইনভেন্টরি থেকে কমাবে, তারপর স্টকে নেই এমন (অর্থাৎ যেগুলোর পরিমাণ 0 হয়ে গেছে) আইটেমের একটি ডিকশনারি রিটার্ন করবে।
julia> inventory = Dict("Banana" => 15, "Apple" => 12, "Orange" => 1, "Milk" => 4);
julia> cart = Dict("Orange" => 1, "Milk" => 2, "Banana" => 3, "Apple" => 2);
julia> update_store_inventory!(inventory, cart)
Dict{String, Int64} with 1 entry:
"Orange" => 0
julia> inventory
Dict{String, Int64} with 4 entries:
"Milk" => 2
"Apple" => 10
"Orange" => 0
"Banana" => 12
ইনভেন্টরি আপডেট করার পাশাপাশি, আপনার অ্যাপ সেটি আবার স্টক করতেও সাহায্য করতে পারে। ক্রেতার অর্ডারের পর যে আইটেমগুলো স্টকে নেই, সেগুলোর একটি মিনি-অর্ডার তৈরি করার ক্ষমতা আপনার MVP-তে থাকা উচিত। এতে একটি বড় অর্ডার শুরু করা সহজ হবে। তার উপর, মাঝে মাঝে সীমিত সময়ের প্রোমোশনাল আইটেম থাকে, যা স্টক তালিকায় থাকে না। প্রোমোশনের সময় শেষ হওয়ার আগেই এগুলো বিক্রি হয়ে গেলে বোঝা যায় এগুলো জনপ্রিয়, আর সেগুলো স্টক তালিকায় যোগ করা যায়।
reorder!(<outofstock>, <stock>) ফাংশনটি তৈরি করুন, যা outofstock এবং stock নেয়।
stock ডিকশনারিতে থাকে সাধারণ স্টক আইটেম এবং সেগুলো আবার অর্ডার করার পরিমাণ।
outofstock ডিকশনারি হলো update_store_inventory!-এর ফলাফল, অর্থাৎ শূন্য পরিমাণের আইটেমের একটি ডিকশনারি।
outofstock-এর পরিমাণগুলো stock-এ থাকা পরিমাণ অনুযায়ী আপডেট করে রিটার্ন করতে হবে।
এছাড়া outofstock-এ থাকা কিন্তু stock-এ নেই এমন আইটেম stock-এ ডিফল্ট পরিমাণ 100 দিয়ে যোগ করতে হবে।
julia> inventory = Dict("Banana" => 15, "Apple" => 12, "Orange" => 1, "Milk" => 4, "Chocolate" => 2);
julia> cart = Dict("Orange" => 1, "Milk" => 2, "Banana" => 3, "Apple" => 2, "Chocolate" => 2);
julia> stock = Dict("Banana" => 150, "Apple" => 120, "Orange" => 120, "Milk" => 45);
julia> outofstock = update_store_inventory!(inventory, cart)
Dict{String, Int64} with 1 entry:
"Orange" => 0
"Chocolate" => 0
julia> reorder!(outofstock, stock)
Dict{String, Int64} with 1 entry:
"Orange" => 120
"Chocolate" => 100
julia> stock
Dict{String, Int64} with 5 entries:
"Milk" => 45
"Apple" => 120
"Chocolate" => 100
"Orange" => 120
"Banana" => 150
Exercism-এ সাইন আপ করুন, Julia ট্র্যাকের 35টি কনসেপ্ট128টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।