مسیرها
/
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 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.