提问人:Philipp M 提问时间:6/20/2023 最后编辑:M. JustinPhilipp M 更新时间:10/29/2023 访问量:156
Javascript - 检查数组中的数组是否相同
Javascript - Check if arrays within an array are the same
问:
在我的情况下,检查数组中的数组是否相同的最佳方法是什么?
var arrSession = [
{
type: '1',
usecase: [ '1' ]
},
{
type: '1',
usecase: [ '1' ]
}
];
var checkUsecase = arrSession.every(isSame);
function isSame(obj, index, arr) {
if (index === 0) {
return true;
} else {
return (
(obj.type === arr[index - 1].type) &&
(obj.usecase === arr[index - 1].usecase)
);
}
}
console.log('checkUsecase:');
console.log(checkUsecase);
数组中的“用例”对象使用字符串“”,而 isSame 函数用于工作。但现在它们也是数组。如何更改isSame功能?
这是一把小提琴:https://jsfiddle.net/3j0odpec/
答:
4赞
Alexander Nenashev
6/20/2023
#1
首先,我们制作一些递归比较函数来遍历嵌套数组/对象。然后我们在数组上运行它,比较当前项目是否等于前一个项目。
这绝对比比较 OP 数据的 JSON.stringized 数组项更快:
const arrSession = [
{
type: '1',
usecase: ['1']
},
{
type: '1',
usecase: ['1']
}
];
const isSameItems = arrSession.every((item, idx, arr) => idx === 0 || isSame(item, arr[idx - 1]));
console.log('the array has all items the same: ', isSameItems);
function isSame(a, b) {
const iterator = Array.isArray(a) && Array.isArray(b) ? a.keys() :
(typeof a === 'object') && (typeof b === 'object') ? Object.keys(a) : null;
if (iterator) {
for (const i of iterator) {
if (!isSame(a[i], b[i])) {
return false;
}
}
return true;
}
return a === b;
}
<script benchmark data-count="1">
const arrSession = JSON.parse(JSON.stringify(Array.from({ length: 300000 }).reduce(arr => arr.push(...[
{
type: '1',
usecase: ['1'],
child: {
type: '1',
usecase: ['1'],
child: {
type: '1',
usecase: ['1'],
child: {
type: '1',
usecase: ['1'],
}
}
},
child: {
type: '1',
usecase: ['1'],
}
}
]) && arr, [])));
// @benchmark JSON.stringify
arrSession.every((item, idx, arr) => idx === 0 || JSON.stringify(item) === JSON.stringify(arr[idx - 1]));
// @benchmark recursive isSame
function isSame(a, b) {
const iterator = Array.isArray(a) && Array.isArray(b) ? a.keys() :
(typeof a === 'object') && (typeof b === 'object') ? Object.keys(a) : null;
if (iterator) {
for (const i of iterator) {
if (!isSame(a[i], b[i])) {
return false;
}
}
return true;
}
return a === b;
}
// @run
arrSession.every((item, idx, arr) => idx === 0 || isSame(item, arr[idx - 1]));
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
评论
0赞
Philipp M
6/27/2023
也是一个很好的答案,感谢您的帮助!非常感谢!很难决定接受哪个答案!
3赞
Peter Seliger
6/20/2023
#2
这个答案也选择了已经提出的一些基于比较
的方法......
const isFullItemEquality = arrSession
.every((item, idx, arr) =>
idx === 0 || isDeepDataStructureEquality(item, arr[idx - 1])
);
...只是它不利用.JSON.stringify
对于性能也很重要的 JSON 符合数据结构的相同性/相等性比较,可以考虑使用以下 isDeepDataStructureEquality
的递归实现......
<script>
// implemented by Peter Seliger
function isDeepDataStructureEquality(a, b) {
let isEqual = Object.is(a, b);
if (!isEqual) {
if (Array.isArray(a) && Array.isArray(b)) {
isEqual = (a.length === b.length) && a.every(
(item, idx) => isDeepDataStructureEquality(item, b[idx])
);
} else if (
a && b
&& (typeof a === 'object')
&& (typeof b === 'object')
) {
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
isEqual = (aKeys.length === bKeys.length) && aKeys.every(
(key, idx) => isDeepDataStructureEquality(a[key], b[key])
);
}
}
return isEqual;
}
</script>
<script>
// implemented by Alexander Nenashev
function isSame(a, b) {
const iterator = Array.isArray(a) && Array.isArray(b) ? a.keys() :
(typeof a === 'object') && (typeof b === 'object') ? Object.keys(a) : null;
if (iterator) {
for (const i of iterator) {
if (!isSame(a[i], b[i])) {
return false;
}
}
return true;
}
return a === b;
}
</script>
<script benchmark data-count="10">
const arrSession = JSON.parse(JSON.stringify(Array
.from({ length: 300000 })
.reduce(arr => arr.push(...[{
type: '1',
usecase: ['1'],
child: {
type: '1',
usecase: ['1'],
child: {
type: '1',
usecase: ['1'],
child: {
type: '1',
usecase: ['1'],
},
},
},
child: {
type: '1',
usecase: ['1'],
}
}]) && arr, [])));
// countercheck implementations with an unequal data structure.
// arrSession.at(-1).child.usecase[0] = 0;
// @benchmark JSON.stringify
arrSession.every((item, idx, arr) =>
idx === 0 || JSON.stringify(item) === JSON.stringify(arr[idx - 1])
);
// @benchmark recursive isSame
arrSession.every((item, idx, arr) =>
idx === 0 || isSame(item, arr[idx - 1])
);
// @benchmark recursive isDeepDataStructureEquality
arrSession.every((item, idx, arr) =>
idx === 0 || isDeepDataStructureEquality(item, arr[idx - 1])
);
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
评论
0赞
Alexander Nenashev
6/20/2023
@PeterSeliger我的坏处是快点。我确实看到,使用仅处理 2 个值 A 和 B 并不是最佳选择,使用与以前相同的逻辑更改它,只是避免了 .所以现在我的函数在速度方面更能与你的函数相媲美。我想你并不反对在你的答案中修复我的代码。这是 StackOverflow 的一些缺点,如果你不够快,即使你的答案是最好的,你也不会得到任何分数......reduce()
reduce()
0赞
Alexander Nenashev
6/20/2023
@PeterSeliger比较数组和对象键长度是明智之举。我之前在我的代码中做了同样的事情,但今天忘记添加这个检查
评论
usecase