I have two lists I need to check whether their elements are equal (not shallow check, for elements I might rely on Kernel.==/2
.)
Currently, I have:
[l1 -- l2] ++ [l2 -- l1] == []
It looks a bit overcomplicated and not quite idiomatic to me. Am I missing something? Is there a better way to compare two lists for equality?
The isEqualCollection() method returns true when the two collections contain exact same elements with exactly the same cardinalities.
We shall write a function areListsEqual() to check if the given two lists are equal element by element. As a pre-requisite, we check if both the given variables are lists, and then compare their lengths. list1 and list2 are equal. list1 and list3 are not equal.
You can compare two array lists using the equals() method of the ArrayList class, this method accepts a list object as a parameter, compares it with the current object, in case of the match it returns true and if not it returns false.
The shortest way I can think of is to sort the lists and compare them:
Enum.sort(l1) == Enum.sort(l2)
This will run in O(n log n)
time instead of O(n ^ 2)
for your Kernel.--/2
based solution.
We can't use a plain Set data structure here since the list can contain duplicates and their counts must be kept track of. We can use a Map which counts the frequency of each element and then to compare them:
iex(1)> l1 = ~w|a a b|a
[:a, :a, :b]
iex(2)> l2 = ~w|a b|a
[:a, :b]
iex(3)> m1 = l1 |> Enum.reduce(%{}, fn x, acc -> Map.update(acc, x, 1, & &1 + 1) end)
%{a: 2, b: 1}
iex(4)> m2 = l2 |> Enum.reduce(%{}, fn x, acc -> Map.update(acc, x, 1, & &1 + 1) end)
%{a: 1, b: 1}
iex(5)> m1 == m2
false
iex(6)> l2 = ~w|a b a|a
[:a, :b, :a]
iex(7)> m2 = l2 |> Enum.reduce(%{}, fn x, acc -> Map.update(acc, x, 1, & &1 + 1) end)
%{a: 2, b: 1}
iex(8)> m1 == m2
true
This is also O(n log n)
so you may want to benchmark the two solutions with the kind of data you'll have to see which performs better.
Dogbert's solution is apt, but it is still in Orcish.
In Erlang this would be:
lists:sort(List1) == lists:sort(List2)
A deep comparison looks very nearly the same, but of course must traverse the structures within each list.
One factor to consider is that very often the ordering of a list is its meaning. Strings are a good example, so are player ranks, start positions, game hotkey locations, and last-used-longest-kept cache lists. So do keep in mind the meaning of the comparison: "Do these two lists contain the same number and type of things?" is not the same as "Are these two lists semantically identical?"
Consider comparing anagrams:
lists:sort("AT ERR GET VICE") == lists:sort("IT ERR ETC GAVE")
That works fine as an anagram comparison, but not at all as a semantic one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With