المسارات
/
Elixir
Elixir
/
التمارين
/
مخزون المتجر
مخزون المتجر

مخزون المتجر

تمرين تعلّمي

مقدمة

Enum

Enum وحدة مفيدة جدًا توفّر مجموعة من الخوارزميات للتعامل مع القوابل للتعداد. فهي تقدّم الترتيب والتصفية والتجميع والعدّ والبحث وإيجاد القيم الصغرى والعظمى، والكثير غير ذلك.

بشكل عام، القابل للتعداد هو أي بيانات يمكن التكرار عليها، أي مجموعة. في Elixir، القابل للتعداد هو أي نوع بيانات يطبّق بروتوكول Enumerable. وأكثرها شيوعًا هي القوائم والخرائط.

تقبل العديد من دوال Enum دالةً كوسيط.

Enum.all?([1, 2, 3, 4, 5], fn x -> x > 3 end)
# => false

أكثر دوال Enum شيوعًا هي map وreduce.

map/2

تتيح لك Enum.map/2 استبدال كل عنصر في قابل للتعداد بعنصر آخر. الوسيط الثاني لـEnum.map/2 هو دالة تقبل العنصر الأصلي وتُرجع بديله.

reduce/3

تتيح لك Enum.reduce/3 اختزال قابل التعداد بأكمله إلى قيمة واحدة. ولتحقيق ذلك، يُستخدم متغير خاص يُسمّى المراكم. ويحمل المراكم الحالة الوسيطة للاختزال بين التكرارات.

الوسيط الثاني لـEnum.reduce/3 هو القيمة الابتدائية للمراكم. والوسيط الثالث هو دالة تقبل عنصرًا ومراكمًا، وتُرجع القيمة الجديدة للمراكم.

العمل مع الخرائط

عند استخدام الخرائط مع دوال Enum، تُحوَّل الخريطة تلقائيًا إلى قائمة من الأزواج الثنائية {key, value}.

لإعادة تحويلها إلى خريطة، استخدم Enum.into/2. وEnum.into/2 دالة تحوّل قابل التعداد إلى قابل للتجميع، أي بنية بيانات تطبّق بروتوكول Collectable. ويمكن اعتبارها عكس Enum.reduce/3.

ولدى Enum أيضًا Enum.into/3. وEnum.into/3 نسخة مختلفة من Enum.into/2 تقبل دالة تحويل تُطبَّق أثناء تحويل قابل التعداد إلى قابل للتجميع.

تحويل الخرائط

بدلًا من استخدام Enum.into/3 أو Enum.map/2 مع Enum.into/2 لتطبيق تحويل (تعيين) على خريطة، يمكننا أيضًا استخدام دالة مخصّصة هي Map.new/2. وهي تعمل تمامًا مثل Enum.into/3 من حيث أنها تقبل قابلًا للتعداد ودالة تحويل، لكنها تُرجع دائمًا خريطة جديدة بدلًا من أن تتيح لنا اختيار قابل للتجميع.

التعليمات

أنت تدير متجر أزياء عبر الإنترنت. يقترب موسم التخفيضات السنوي الكبير، لذا عليك جرد مخزونك للتأكد من أنك مستعد.

تُمثَّل كل قطعة في المخزون بخريطة، والمخزون كله مصفوفة من هذه الخرائط.

%{
  name: "White Shirt",
  price: 40,
  quantity_by_size: %{s: 3, m: 7, l: 8, xl: 4}
}

1. رتّب القطع حسب السعر

نفّذ الدالة sort_by_price/1. يجب أن تأخذ المخزون وتُرجع مرتبًا حسب سعر القطعة، تصاعديًا.

BoutiqueInventory.sort_by_price([
  %{price: 65, name: "Maxi Brown Dress", quantity_by_size: %{}},
  %{price: 50, name: "Red Short Skirt", quantity_by_size: %{}},
  %{price: 50, name: "Black Short Skirt", quantity_by_size: %{}},
  %{price: 20, name: "Bamboo Socks Cats", quantity_by_size: %{}}
])

# => [
#      %{price: 20, name: "Bamboo Socks Cats", quantity_by_size: %{}},
#      %{price: 50, name: "Red Short Skirt", quantity_by_size: %{}},
#      %{price: 50, name: "Black Short Skirt", quantity_by_size: %{}},
#      %{price: 65, name: "Maxi Brown Dress", price: 65, quantity_by_size: %{}}
#    ]

2. اعثر على كل القطع التي ينقصها سعر

بعد ترتيب مخزونك حسب السعر، لاحظت أنك أخطأت عند الجرد ونسيت تسجيل أسعار بعض القطع.

نفّذ الدالة with_missing_price/1. يجب أن تأخذ المخزون وتُرجع مصفوفة من القطع التي ليس لها أسعار.

BoutiqueInventory.with_missing_price([
  %{price: 40, name: "Black T-shirt", quantity_by_size: %{}},
  %{price: nil, name: "Denim Pants", quantity_by_size: %{}},
  %{price: nil, name: "Denim Skirt", quantity_by_size: %{}},
  %{price: 40, name: "Orange T-shirt", quantity_by_size: %{}}
])

# => [
#      %{price: nil, name: "Denim Pants", quantity_by_size: %{}},
#      %{price: nil, name: "Denim Skirt", quantity_by_size: %{}}
#    ]

3. حدّث أسماء القطع

لاحظت أن بعض أسماء القطع تحتوي على كلمة لم تعد ترغب في استخدامها. الآن عليك تحديث كل أسماء القطع التي تحتوي على تلك الكلمة.

نفّذ الدالة update_names/3. يجب أن تأخذ المخزون، والكلمة القديمة التي تريد إزالتها، والكلمة الجديدة التي تريد استخدامها بدلًا منها. ويجب أن تُرجع مصفوفة من القطع بأسماء محدّثة.

BoutiqueInventory.update_names(
  [
    %{price: 40, name: "Black T-shirt", quantity_by_size: %{}},
    %{price: 70, name: "Denim Pants", quantity_by_size: %{}},
    %{price: 65, name: "Denim Skirt", quantity_by_size: %{}},
    %{price: 40, name: "Orange T-shirt", quantity_by_size: %{}}
  ],
  "T-shirt",
  "Tee"
)

# => [
#      %{price: 40, name: "Black Tee", quantity_by_size: %{}},
#      %{price: 70, name: "Denim Pants", quantity_by_size: %{}},
#      %{price: 65, name: "Denim Skirt", quantity_by_size: %{}},
#      %{price: 40, name: "Orange Tee", quantity_by_size: %{}}
#    ]

4. زد كمية القطعة

كانت بعض القطع تُبيع جيدًا بشكل خاص، لذا طلبت المزيد منها بجميع المقاسات.

نفّذ الدالة increase_quantity/2. يجب أن تأخذ قطعة واحدة وعددًا n، وتُرجع تلك القطعة مع زيادة الكمية لكل مقاس بمقدار n.

BoutiqueInventory.increase_quantity(
  %{
    name: "Polka Dot Skirt",
    price: 68,
    quantity_by_size: %{s: 3, m: 5, l: 3, xl: 4}
  },
  6
)

# => %{
#      name: "Polka Dot Skirt",
#      price: 68,
#      quantity_by_size: %{l: 9, m: 11, s: 9, xl: 10}
#    }

5. احسب الكمية الإجمالية للقطعة

لمعرفة المساحة التي تحتاجها في المخزن، عليك معرفة إجمالي ما لديك من كل قطعة.

نفّذ الدالة total_quantity/1. يجب أن تأخذ قطعة واحدة وتُرجع عدد القطع الإجمالي لديك، بأي مقاس.

BoutiqueInventory.total_quantity(%{
  name: "Red Shirt",
  price: 62,
  quantity_by_size: %{s: 3, m: 6, l: 5, xl: 2}
})

# => 16
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Elixir Exercism

مستعد لبدء مخزون المتجر؟

سجّل في Exercism لتتعلّم وتتقن Elixir عبر 58 مفهومًا168 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.