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

我知道我可以用循环来完成,但是我试图找到一种优雅的方法:

我有两个参差不齐的数组(数组数组) :

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

我想使用 lodash来确认上面两个锯齿数组是相同的。我所说的“相同”是指 array1中没有不包含在 array2中的项目。注意,锯齿数组中的项实际上是数组。所以我想比较一下内部数组。

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

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

或者

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

这两个工作,因为信将永远是有序的。


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

241555 次浏览

如果对外部数组排序,则可以使用 _.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()不会改变数组。

我说的“相同”是指数组1中没有不包含在数组2中的项。

您可以为此使用 flatten ()和 different () ,如果您不关心 array2中是否有 没有array1中的项,那么这种方法可以很好地工作。听起来像是在问 是 array1的一个子集

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添加示例链接

PureJS (当数组和子数组具有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);

您可以使用 lodashxor

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

如果您认为 array [1,1]与 array [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]不起作用,但是只要数组是基元元素,就可以比较数组内容。方法,并针对使用不同顺序的相同值的两个数组的字符串进行测试。不能使用对象类型。我建议创建一个通用助手,它根据需要比较的类型调用助手函数。尝试使用非常奇妙的 loash 库中的 _.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
}

如果没有不同的字符并且数组长度相同,那么它们就是相同的。