MapSet
MapSet مجموعة من القيم الفريدة، وهي تمثّل المجموعات في Elixir. يمكنها أن تحتوي قيمًا من أي نوع، ومن دون أي مفهوم للترتيب.
لاحظ أن وحدة Set موجودة أيضًا، لكن استخدامها مهجور لصالح MapSet.
يمكنك إنشاء المجموعات باستخدام MapSet.new/0 وMapSet.new/1 وMapSet.new/2، وتحويلها إلى قوائم باستخدام MapSet.to_list/1.
MapSet.new()
# => MapSet.new([])
MapSet.new([2, 3, 3, 3, 1, 1, 2, "hello"])
# => MapSet.new([1, 2, 3, "hello"])
MapSet.new([2, 3, 3, 3, 1, 1, 2], fn n -> 10 * n end)
# => MapSet.new([10, 20, 30])
[2, 3, 3, 3, 1, 1, 2] |> MapSet.new() |> MapSet.to_list()
# => [1, 2, 3]
لاحظ أنه بما أن مجموعات MapSet ليس لها مفهوم للترتيب، فليس مضمونًا أن تُرجع MapSet.to_list/1 قائمة مرتّبة.
يمكنك إضافة العناصر أو حذفها باستخدام MapSet.put/2 وMapSet.delete/2.
يمكنك الاستعلام عن محتويات مجموعة باستخدام الدوال MapSet.size/1 وMapSet.member?/2، ومقارنة المجموعات باستخدام MapSet.equal?/2 وMapSet.subset?/2 وMapSet.disjoint?/2.
a = MapSet.new([1, 10])
b = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
MapSet.size(b)
# => 10
MapSet.member?(a, 10)
# => true
MapSet.subset?(a, b)
# => true
MapSet.disjoint?(a, b)
# => false
يمكن دمج مجموعات MapSet باستخدام MapSet.union/2 وMapSet.intersection/2 وMapSet.difference/2 وMapSet.symmetric_difference/2.
a = MapSet.new([1, 10, 100])
b = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
MapSet.union(a, b)
# => MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100])
MapSet.intersection(a, b)
# => MapSet.new([1, 10])
MapSet.difference(a, b)
# => MapSet.new([100])
MapSet.difference(b, a)
# => MapSet.new([2, 3, 4, 5, 6, 7, 8, 9])
MapSet.symmetric_difference(b, a)
# => MapSet.new([2, 3, 4, 5, 6, 7, 8, 9, 100])
يمكنك تصفية المجموعات وتقسيمها باستخدام MapSet.filter/2 وMapSet.reject/2 وMapSet.split_with/2.
a = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
even = fn n -> rem(n, 2) == 0 end
MapSet.filter(a, even)
# => MapSet.new([2, 4, 6, 8, 10])
MapSet.reject(a, even)
# => MapSet.new([1, 3, 5, 7, 9])
MapSet.split_with(a, even)
# => {MapSet.new([2, 4, 6, 8, 10]), MapSet.new([1, 3, 5, 7, 9])}
يبدو أن حنينك إلى بطاقات Blorkemon™️ لا يُظهر أي علامة على التباطؤ، حتى إنك بدأت بجمعها من جديد، وتستقطب أصدقاءك لينضموا إليك.
في هذا التمرين، تُمثَّل مجموعة البطاقات بواسطة MapSet، لأن البطاقات المكررة لا أهمية لها عندما يكون هدفك الحصول على جميع البطاقات الموجودة.
أنت تتوق حقًا إلى أن ينضم أصدقاؤك إلى جنون Blorkemon™️، وأفضل طريقة هي أن تبدأ مجموعتهم بمنحهم بطاقة واحدة.
نفّذ GottaSnatchEmAll.new_collection، التي تحوّل بطاقة إلى مجموعة.
GottaSnatchEmAll.new_collection("Newthree")
# => MapSet.new(["Newthree"])
بمجرد أن تحصل على مجموعة، تصير لها حياة خاصة بها، ولا بد أن تنمو.
نفّذ GottaSnatchEmAll.add_card، التي تأخذ بطاقة ومجموعة، وتُرجع زوجًا من قيمتين: قيمة منطقية تشير إلى ما إذا كانت البطاقة موجودة في المجموعة بالفعل، والمجموعة مع البطاقة المضافة.
GottaSnatchEmAll.add_card("Scientuna", MapSet.new(["Newthree"]))
# => {false, MapSet.new(["Newthree", "Scientuna"])}
الآن بعد أن عاد أصدقاؤك إلى جنون Blorkemon™️، يمكنك الاستفادة من ذلك لتنمية مجموعتك عبر مقايضة البطاقات.
ليست كل مقايضة جديرة بالقيام بها، أو ممكنة أصلًا. لا يمكنك مقايضة بطاقة لا تملكها، ولا ينبغي أن تقايض بطاقة بأخرى تملكها بالفعل.
نفّذ GottaSnatchEmAll.trade_card، التي تأخذ بطاقتين للمقايضة (بطاقتك وبطاقتهم) ومجموعتك الحالية.
القيمة المُرجَعة هي زوج من قيمتين: قيمة منطقية تبيّن ما إذا كانت المقايضة ممكنة وجديرة بالقيام بها، والمجموعة التي ستنتهي إليها إذا أجريت المقايضة (حتى لو لم تكن ممكنة فعليًا).
GottaSnatchEmAll.trade_card("Scientuna", "Newthree", MapSet.new(["Scientuna"]))
# => {true, MapSet.new(["Newthree"])}
تجد مخزونًا قديمًا من البطاقات في سوق للسلع المستعملة. عليك أن ترتّب البطاقات وتزيل المكرر منها لتقارن المصفوفة بمجموعتك.
نفّذ GottaSnatchEmAll.remove_duplicates التي ترتّب مصفوفة من البطاقات وتُرجع مصفوفة من البطاقات المرتّبة والفريدة.
GottaSnatchEmAll.remove_duplicates(["Newthree", "Newthree", "Newthree", "Scientuna"])
# => ["Newthree", "Scientuna"]
حان وقت الاعتزاز بمجموعتك.
نفّذ GottaSnatchEmAll.extra_cards، التي تأخذ مجموعتك ومجموعة أخرى، وتُرجع عدد البطاقات التي لا تملكها المجموعة الأخرى.
GottaSnatchEmAll.extra_cards(MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"]))
# => 0
تجتمع أنت وأصدقاؤك المتحمسون لـ Blorkemon™️ وتتساءلون عن البطاقات الأكثر شيوعًا.
نفّذ GottaSnatchEmAll.boring_cards، التي تأخذ مصفوفة من المجموعات وتُرجع مصفوفة من البطاقات المرتّبة التي تملكها جميع المجموعات.
GottaSnatchEmAll.boring_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => ["Scientuna"]
هل تملك أنت وأصدقاؤك مجتمعين كل بطاقات Blorkemon™️؟
نفّذ GottaSnatchEmAll.total_cards، التي تأخذ مصفوفة من المجموعات وتُرجع العدد الإجمالي للبطاقات المختلفة في جميع المجموعات.
GottaSnatchEmAll.total_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => 2
سيأتي ابن أخيك لزيارتك قريبًا، وتشعر برغبة في إبهاره. الأطفال يحبون الأشياء اللامعة، أليس كذلك؟ يمكن أن تكون بطاقات Blorkemon™️ لامعة!
نفّذ GottaSnatchEmAll.split_shiny_cards، التي تأخذ مجموعة وتُرجع زوجًا من مصفوفتين من البطاقات المرتّبة: واحدة تضم كل البطاقات التي تبدأ بـ "Shiny" وأخرى بالبطاقات الأخرى.
GottaSnatchEmAll.split_shiny_cards(MapSet.new(["Newthree", "Scientuna", "Shiny Scientuna"]))
# => {["Shiny Scientuna"], ["Newthree", "Scientuna"]}
سجّل في Exercism لتتعلّم وتتقن Elixir عبر 58 مفهومًا168 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.