Рамда: Проверьте, равны ли два массива - PullRequest
4 голосов
/ 09 апреля 2019

Я все еще изучаю функциональное программирование на JavaScript, и мне очень нравится использовать Ramda.

У меня есть два массива. Я хочу проверить, имеют ли они одинаковые значения, независимо от порядка. Я думал, что это можно сделать с помощью equals. Но, видимо,

R.equals([1, 2], [2, 1]) // false

Есть ли эффективный способ проверить, равны ли два массива? Мои массивы состоят из объектов и могут содержать до значений X * 10E4, если это имеет значение 1

Ответы [ 3 ]

4 голосов
/ 09 апреля 2019

Я бы использовал eqBy с countBy:

Вы можете использовать countBy для построения "профиля" вашего массива:

countBy(identity, [1, 2]);
//=> {"1": 1, "2": 1}

countBy(identity, [2, 1]);
//=> {"1": 1, "2": 1}

Затем вы можете сравнить два профиля с eqBy:

eqBy(countBy(identity), [1,2], [2,1])
//=> true
4 голосов
/ 09 апреля 2019

Причина, по которой это не работает - помимо того факта, что функция Ramda называется equals, а не isEqual - заключается в том, что массивы являются внутренне упорядоченными контейнерами.[1, 2] существенно отличается от [2, 1].

Стандартный неупорядоченный контейнер - Set.К сожалению, это основано на равенстве ссылок, поэтому он может получить несколько копий элементов, которые Рамда будет считать равными.Поэтому наиболее очевидный ответ не будет работать должным образом:

// ** Broken -- do not use **
const eqValues = (a1, a2) => R.equals(new Set(a1), new Set(a2))

console.log(eqValues(
  [{x: 1}, {x: 2}], 
  [{x: 1}, {x: 3}]
)) //=> false
console.log(eqValues(
  [{x: 1}, {x: 2}], 
  [{x: 2}, {x: 1}]
)) //=> true

, потому что в этом случае произойдет сбой из-за проверки длины:

console.log(eqValues(
  [{x: 1}, {x: 2}, {x: 2}], 
  [{x: 2}, {x: 1}]
)) //=> false, but should be true, since {x: 2} is the same as {x: 2}

Рамда не раскрывает свой внутренний _Setтип - и, возможно, он должен - но он использует их в таких функциях, как difference, и через это в symmetricDifference.Это подходящие функции для проверки значений, чье равенство значений находится под вопросом.

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

const eqValues = compose(isEmpty, symmetricDifference)

console.log(eqValues(
  [{x: 1}, {x: 2}], 
  [{x: 1}, {x: 3}]
)) //=> false
console.log(eqValues(
  [{x: 1}, {x: 2}], 
  [{x: 2}, {x: 1}]
)) //=> true
console.log(eqValues(
  [{x: 1}, {x: 2}], 
  [{x: 2}, {x: 1}, {x: 1}]
)) //=> true
<script src="https://bundle.run/ramda@0.26.1"></script><script>
const {compose, isEmpty, symmetricDifference} = ramda;   </script>

Однако, если вам нужно проверить кратности - то есть, arr1 содержит две копии {x: 42}, а arr2 имеет только одну, поэтомуони разные - тогда я бы использовал ответ от customcommander.

2 голосов
/ 09 апреля 2019

Есть много способов достичь этого с Рамдой

Тот, кто приходит на ум, это

R.length([1,2]) === R.length([2,1]) && R.isEmpty(R.symmetricDifference([1,2], [2,1]))

edit : использование R.difference вместо R.symmetricDifference не сработает, так как первый возвращает только элементы в первом списке, которые не содержатся во втором списке.

R.difference([1,2], [2,1,3]) // -> []

...