Как группировать на карте? - PullRequest
1 голос
/ 17 октября 2019

Я пытаюсь отфильтровать, какой товар продается больше всего за определенный месяц. У меня есть набор данных, из которого я читаю файл.

  %{
  "Almond Fudge" => [
    %{date: "2019-01-01", quantity: 1},
    %{date: "2019-01-02", quantity: 1},
    %{date: "2019-01-04", quantity: 3},
    %{date: "2019-01-05", quantity: 5}],

"Banana Split" => [
    %{date: "2019-01-02", quantity: 3},
    %{date: "2019-01-02", quantity: 5},
    %{date: "2019-01-02", quantity: 3},
    %{date: "2019-01-02", quantity: 5}]
   }

Так что теперь у него есть что-то вроде карты, и внутри я создал другую карту, чтобы отфильтровать данные, чтобы увидеть, какой и сколько предметов покупается на определенную дату.

Теперь я пытаюсь выяснить, как я могу просто вернуть и месяц, и сумму всего.

Так что это должно дать мне что-то вроде этого:

Для миндальной помадки

%{date: "2019-01", quantity: 10}

То, что я пробовал до сих пор

items = rows
        |> Enum.map( fn row -> headers |> Enum.zip(row) |> Map.new end)
        |> Enum.group_by(fn %{"SKU"=> product_name} -> product_name end, fn %{"Quantity"=> quantity, "Date"=> date } -> %{ date: date, quantity: String.to_integer(quantity) } end )
        |> IO.inspect

1 Ответ

0 голосов
/ 17 октября 2019

С такими данными, как:

data = %{
  "Almond Fudge" => [
    %{date: "2019-01-01", quantity: 1},
    %{date: "2019-01-02", quantity: 1},
    %{date: "2019-01-04", quantity: 3},
    %{date: "2019-01-05", quantity: 5}
  ],
  "Banana Split" => [
    %{date: "2019-01-02", quantity: 3},
    %{date: "2019-01-02", quantity: 5},
    %{date: "2019-01-02", quantity: 3},
    %{date: "2019-01-02", quantity: 5}
  ]
}

Вы можете сделать что-то вроде этого:

Enum.map(data, fn {product, sales} ->              
  {
    product,                          
    Enum.group_by(sales, &(String.slice(&1.date, 0, 7)), &(&1.quantity))
    |> Enum.map(fn {k, v} ->
      {k, Enum.sum(v)}
    end) |> Map.new()
  }
end) |> Map.new()

Эта строка: Enum.group_by(sales, &(&1.date), &(&1.quantity)) создаст карты с датами в качестве ключей и спискомзначений в качестве значений.

И затем вы можете преобразовать это в карту с датой в качестве ключей и общей суммой в виде значений, в которые она будет добавлена: Enum.map(fn {k, v} -> {k, Enum.sum(v)} end) |> Map.new()

И окончательный результат будет:

%{"Almond Fudge" => %{"2019-01" => 10}, "Banana Split" => %{"2019-01" => 16}}

Или, если вы хотите получить точный результат, если вы не хотите указывать даты в качестве ключей, вы можете заменить эту строку на: |> Enum.map(fn {k, v} -> %{date: k, quantity: Enum.sum(v)} end)}

Оставив вам:

Enum.map(data, fn {product, sales} ->                                                                          
  {
    product,                                                                                                    
    Enum.group_by(sales, &(String.slice(&1.date, 0, 7)), &(&1.quantity))
    |> Enum.map(fn {k, v} -> %{date: k, quantity: Enum.sum(v)} end)}             
end) |> Map.new() 

В результате:

%{
  "Almond Fudge" => [%{date: "2019-01", quantity: 10}],
  "Banana Split" => [%{date: "2019-01", quantity: 16}]
}

Спасибо @zwippie за указание на String.slice. Я не поняла, что ты спрашиваешь месяц. String.slice/3 примет строку, начальную позицию и длину. Таким образом, нарезка строки даты от 0 до 7 цифр приведет к появлению строк с указанием года и месяца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...