Boutique inventory sort question

Hi,
currently I’m stuck at the Elixir’s track Boutique Inventory in Elixir on Exercism practice. I can’t manage to make the tests for the sort_by_price function pass. What confuses me is with which result the test fails.

My current implementation looks like this:

 def sort_by_price(inventory) do
    sortFn = fn(a,b) ->
      if a["price"] == b["price"] do
        false
      else
        a["price"] < b["price"]
      end
    end

    Enum.sort(inventory, sortFn)
  end

The failing test looks like this:

 test sort_by_price/1 the order of items of equal price is preserved (BoutiqueInventoryTest)
     test/boutique_inventory_test.exs:24
     Assertion with == failed
     code:  assert BoutiqueInventory.sort_by_price([
              %{price: 65, name: "Maxi Yellow Summer Dress", quantity_by_size: %{}},
              %{price: 60, name: "Cream Linen Pants", quantity_by_size: %{}},
              %{price: 33, name: "Straw Hat", quantity_by_size: %{}},
              %{price: 60, name: "Brown Linen Pants", quantity_by_size: %{}}
            ]) == [
              %{price: 33, name: "Straw Hat", quantity_by_size: %{}},
              %{price: 60, name: "Cream Linen Pants", quantity_by_size: %{}},
              %{price: 60, name: "Brown Linen Pants", quantity_by_size: %{}},
              %{price: 65, name: "Maxi Yellow Summer Dress", quantity_by_size: %{}}
            ]
     left:  [%{name: "Brown Linen Pants", price: 60, quantity_by_size: %{}}, %{name: "Straw Hat", price: 33, quantity_by_size: %{}}, %{name: "Cream Linen Pants", price: 60, quantity_by_size: %{}}, %{name: "Maxi Yellow Summer Dress", price: 65, quantity_by_size: %{}}]
     right: [%{name: "Straw Hat", price: 33, quantity_by_size: %{}}, %{name: "Cream Linen Pants", price: 60, quantity_by_size: %{}}, %{name: "Brown Linen Pants", price: 60, quantity_by_size: %{}}, %{name: "Maxi Yellow Summer Dress", price: 65, quantity_by_size: %{}}]
     stacktrace:
       test/boutique_inventory_test.exs:25: (test)

  * test with_missing_price/1 works for an empty inventory (0.00ms) [L#41]
  * test with_missing_price/1 filters out items that do have a price (0.00ms) [L#46]

There are two things that confuse me:

  1. if I change the false in the if block to true, I have an additional test failing. I don’t understand why because in the documentation of the sort function it says " The given function should compare two arguments, and return true if the first argument precedes or is in the same place as the second one.", so in my opinion returning true would be the correct behaviour in case of equality.
  2. I would understand if the sort was not stable, i.e. the two 60-price-items swapped. But I don’t understand how it is possible that my result is not sorted correctly at all (33, 60, 60, 65)

Thank you very much for your help!

Hello!
Your main issue is using a["price"] instead of a[:price] or even a.price. It would work for a map indexed with strings %{ "price" => 65}, but not for one indexed with atoms %{price: 65}. With the wrong key you were comparing nil to nil all the time.
This should unblock you :slight_smile:

2 Likes

Thank you so much! I completely overlooked that one.