Лучшая структура данных Elixir для тестирования сравнения - PullRequest
1 голос
/ 17 июня 2019

У меня есть два выходных массива, где мне нужно перебирать каждую структуру и сравнивать количество совпадений источника.Сравнение должно быть меньше или равно.Мои выходные данные выглядят так:

output_1: [%{source: "facebook", count: 3}, %{count: 1, source: "linkedin"}]

output_2: [%{source: "facebook", count: 2}, %{count: 1, source: "linkedin"}]

Какую структуру данных лучше всего реализовать, чтобы сделать Enumerables проще и эффективнее сравнивать?

Ответы [ 3 ]

1 голос
/ 18 июня 2019

Если ваш заказ не гарантирован, я предпочитаю превратить список ссылок в карту и сравнивать вещи по источникам.

iex> output_1 = [%{source: "facebook", count: 3}, %{count: 1, source: "linkedin"}]
[%{count: 3, source: "facebook"}, %{count: 1, source: "linkedin"}]
iex> output_2 = [%{source: "facebook", count: 2}, %{count: 1, source: "linkedin"}]
[%{count: 2, source: "facebook"}, %{count: 1, source: "linkedin"}]
iex> limits = Map.new(output_1, &{&1.source, &1.count})
%{"facebook" => 3, "linkedin" => 1}
iex> Enum.all?(output_2, & &1.count <= limits[&1.source])
true
1 голос
/ 18 июня 2019

Ваш текущий формат вывода должен быть очень эффективным со следующим кодом.Вы не сказали, какой ожидаемый результат вы получили, и в каком направлении должно выполняться сравнение: output2 <= output1 или output1 <= output2, поэтому я предполагаю список логических значений и output1 <= output2:

defmodule A do

  def compare([%{count: count1}|maps1], [%{count: count2}|maps2]) do
    [count1 <= count2 | compare(maps1, maps2) ]
  end
  def compare([], []), do: []

end

Следующее делает то же самое, и его легче придумать и понять:

defmodule A do
  def compare(list1, list2), do: _compare(list1, list2, [])

  defp _compare([%{count: count1}|maps1], [%{count: count2}|maps2], acc) do
    _compare(maps1, maps2, [count1 <= count2 | acc])      
  end
  defp _compare([], [], acc) do
    Enum.reverse(acc)
  end

end

В iex:

~/elixir_programs$ iex a.ex
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> out1 = [%{source: "facebook", count: 3}, %{count: 1, source: "linkedin"}]
[
  %{count: 3, source: "facebook"},
  %{count: 1, source: "linkedin"}
]

iex(2)> out2 = [%{source: "facebook", count: 2}, %{count: 1, source: "linkedin"}]
[
  %{count: 2, source: "facebook"},
  %{count: 1, source: "linkedin"}
]

iex(3)> A.compare(out1, out2)                               
[false, true]        

Если вместо этого вам нужен результатодин логический, то есть счетчик facebook меньше или равен И счетчик кодов меньше или равен, вы можете изменить аккумулятор :

defmodule A do
  def compare(list1, list2), do: _compare(list1, list2, true)

  defp _compare([%{count: count1}|maps1], [%{count: count2}|maps2], true) do
    _compare(maps1, maps2, count1 <= count2)

  end
  defp _compare(_, _, false), do: false  #If you find a false comparison, stop and return false
  defp _compare([], [], _), do: true

end

В iex:

iex(22)> c "a.ex"
warning: redefining module A (current version defined in memory)
  a.ex:1
[A]

iex(23)> A.compare(out1, out2)
false

Это также работает:

defmodule A do
  def compare(list1, list2) do
    List.first(list1)[:count] <= List.first(list2)[:count]
    and
    List.last(list1)[:count] <= List.last(list2)[:count]
  end
end

Какую структуру данных лучше всего реализовать, чтобы сделать Enumerables наиболее простым и эффективным для сравнения?

В противном случае я бы назначил список ключевых слов , например:

[facebook: 3, linkedin: 1]
[facebook: 2, linkedin: 1]
0 голосов
/ 17 июня 2019

Самым простым, вероятно, будет использование Enum.zip/2 с Enum.all?/2. Что-то вроде следующего должно работать

output_1 = Enum.sort(output_1, fn a, b -> a.source <= b.source end)
output_2 = Enum.sort(output_2, fn a, b -> a.source <= b.source end)

output_1
|> Enum.zip(output_2)
|> Enum.all?(fn a, b -> a.count == b.count end)
...