Javascript - 检查数组中的数组是否相同

问题描述 投票:0回答:2

在我的情况下,检查数组中的数组是否相同的最佳方法是什么?

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);

数组中的“usecase”对象是一个字符串“”,并且 isSame 函数可以工作。但现在它们也是数组。如何更改 isSame 函数?

这是一个小提琴:https://jsfiddle.net/3j0odpec/

javascript arrays data-structures comparison equality
2个回答
4
投票

首先我们创建一些递归比较函数来遍历嵌套数组/对象。然后我们对数组运行它,比较当前项与前一项是否相等。

而且它绝对比比较 OP 数据的 JSON.stringified 数组项更快:

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>


3
投票

这个答案也选择了已经提出的基于

some
的比较方法...

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>

© www.soinside.com 2019 - 2024. All rights reserved.