使用lodash比较锯齿状数组(项目无序存在)

Using lodash to compare jagged arrays (items existence without order)

我知道我可以使用循环来做到这一点,但我正试图找到一种优雅的方式来做到这一点:

我有两个交错的数组(数组的数组):

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];

我想用lodash来确认上面两个锯齿状数组是一样的。 'the same' 我的意思是 array1 中没有不包含在 array2 中的项目。请注意,交错数组中的项目实际上是数组。所以我想比较内部数组。

在检查这些项目之间的相等性方面:

['a', 'b'] == ['b', 'a'] 

['a', 'b'] == ['a', 'b'] 

两者都有效,因为字母总是按顺序排列的。


更新:最初的问题是谈论“数组”(而不是锯齿状数组),多年来许多人讨论(并添加了答案)关于比较简单的一维数组(没有注意到问题中提供的示例实际上与他们期望的简单一维数组并不相似)。

如果对外部数组进行排序,则可以使用 _.isEqual(),因为内部数组已经排序。

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];
_.isEqual(array1.sort(), array2.sort()); //true

请注意,.sort() 会改变数组。如果这对您来说是个问题,请先使用(例如).slice() 或扩展运算符 (...).

制作副本

或者,按照 Daniel Budick 在下面评论中的建议进行操作:

_.isEqual(_.sortBy(array1), _.sortBy(array2))

Lodash 的 sortBy() 不会改变数组。

By 'the same' I mean that there are is no item in array1 that is not contained in array2.

您可以为此使用 flatten() 和 difference(),如果您不在乎 array2 中是否有 没有的项目,这会很有效 array1。听起来你在问 array1 是 array2 的子集吗?

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];

function isSubset(source, target) {
    return !_.difference(_.flatten(source), _.flatten(target)).length;
}

isSubset(array1, array2); // → true
array1.push('d');
isSubset(array1, array2); // → false
isSubset(array2, array1); // → true

我们可以用_.difference函数看看有没有区别。

function isSame(arrayOne, arrayTwo) {
   var a = _.uniq(arrayOne),
   b = _.uniq(arrayTwo);
   return a.length === b.length && 
          _.isEmpty(_.difference(b.sort(), a.sort()));
}

// examples
console.log(isSame([1, 2, 3], [1, 2, 3])); // true
console.log(isSame([1, 2, 4], [1, 2, 3])); // false
console.log(isSame([1, 2], [2, 3, 1])); // false
console.log(isSame([2, 3, 1], [1, 2])); // false

// Test cases pointed by Mariano Desanze, Thanks.
console.log(isSame([1, 2, 3], [1, 2, 2])); // false
console.log(isSame([1, 2, 2], [1, 2, 2])); // true
console.log(isSame([1, 2, 2], [1, 2, 3])); // false

希望对您有所帮助。

StackBlitz

添加示例 link

PURE JS(当数组和子数组有超过 2 个任意顺序的元素时也适用)。如果字符串包含 , 用作 join('-') 参数字符(可以是 utf),它不在字符串

中使用
array1.map(x=>x.sort()).sort().join() === array2.map(x=>x.sort()).sort().join()

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['b', 'a']];

var r = array1.map(x=>x.sort()).sort().join() === array2.map(x=>x.sort()).sort().join();

console.log(r);

您可以为此使用 lodashs xor

doArraysContainSameElements = _.xor(arr1, arr2).length === 0

如果您认为数组 [1, 1] 与数组 [1] 不同,那么您可能会像这样提高性能:

doArraysContainSameElements = arr1.length === arr2.length && _.xor(arr1, arr2).length === 0

这里已经有答案了,这里是我的纯JS实现。我不确定它是否是最佳的,但它确实是透明的、可读的和简单的。

// Does array a contain elements of array b?
const union = new Set([...a, ...b]);
const contains = (a, b) => union.size === a.length && union.size === b.length;
// Since order is not important, just data validity.
const isEqualSet = (a, b) => union.contains(a, b) || union.contains(b, a)

contains()的基本原理是,如果a确实包含b的所有元素,那么将它们放在同一个集合中不会改变大小。

例如,如果 const a = [1,2,3,4]const b = [1,2],则 new Set([...a, ...b]) === {1,2,3,4}。如您所见,结果集具有与 a.

相同的元素

从那里开始,为了使它更简洁,我们可以将其归结为以下内容:

const isEqualSet = (a: string[], b: sting[]): boolean => {
  const union = new Set([...a, ...b])
  return union.size === a.length && union.size === b.length;
}

编辑:这不适用于 obj[{a: true}, true, 3] 但可能会比较数组内容,只要它们是原始元素即可。方法修复并针对两个数组使用不同顺序使用相同值的字符串进行测试。不适用于对象类型。我建议制作一个通用助手,它根据需要比较的类型调用助手函数。从非常棒的 lodash 库中尝试 _.isEqual(a. b);

编辑:我错过了这个问题的多维方面,所以我把它留在这里以防它帮助人们比较一维数组

这是一个老问题,但我在使用 .sort()sortBy() 时遇到了速度问题,所以我改用了这个:

function arraysContainSameStrings(array1: string[], array2: string[]): boolean {
  return (
    array1.length === array2.length &&
    array1.every((str) => array2.includes(str)) &&
    array2.every((str) => array1.includes(str))
  )
}

它旨在快速失败,并且对我来说工作正常。

发布这个解决方案我肯定觉得很不干净,但是:

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];
_.isMatch([array1], [array2]) && _.isMatch([array2], [array1]) // true

array1 = [['b', 'a'], ['c', 'b']];
array2 = [['b', 'c'], ['a', 'b']];
_.isMatch([array1], [array2]) && _.isMatch([array2], [array1]) // also true

请注意,您必须array1array2 包装到容器(数组、对象)中才能使其工作?为什么?这可能有一个非常愚蠢的原因。

import { differenceBy } from 'lodash'

export default function (arr1, arr2) {
    return !differenceBy(arr1, arr2).length && arr1.length === arr2.length
}

如果没有不同的字符且数组长度相同,则它们相同。