skip to Main Content

Whats the best way to check if the arrays within an array are the same in my case?

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

The ‘usecase’ object within the array use to be a string ” and the isSame function used to work. But now they are arrays too. How to change the isSame function?

Here is a fiddle: https://jsfiddle.net/3j0odpec/

2

Answers


  1. First we make some recursive compare function to walk nested arrays/objects. Then we run it over the array comparing that the current item is equal to the previous one.

    While it’s a bit slower than comparing JSON.stringified array items of the OP’s data:

    enter image description here

    It wins with more complex objects:

    enter image description here

    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 objectCount = [a, b].reduce((sum, item) => sum + (item.__proto__.constructor.name === 'Object' ? 1 : 0), 0);
        const arrayCount = objectCount ? 0 : [a, b].reduce((sum, item) => sum + (Array.isArray(item) ? 1 : 0), 0);
    
        if (arrayCount === 2 || objectCount === 2) {
            for (const i of arrayCount ? a.keys() : Object.keys(a)) {
                if (!isSame(a[i], b[i])) {
                    return false;
                }
            }
            return true;
        }
        
        if (arrayCount || objectCount) {
            return false;
        }
    
        return a === b;
    
    
    }
    <script benchmark data-count="1">
    
        const arrSession = 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
    
        arrSession.every((item, idx, arr) => idx === 0 || isSame(item, arr[idx - 1]));
    
        function isSame(a, b) {
    
            const objectCount = [a, b].reduce((sum, item) => sum + (item.__proto__.constructor.name === 'Object' ? 1 : 0), 0);
            const arrayCount = objectCount ? 0 : [a, b].reduce((sum, item) => sum + (Array.isArray(item) ? 1 : 0), 0);
    
            if (arrayCount === 2 || objectCount === 2) {
                for (const i of arrayCount ? a.keys() : Object.keys(a)) {
                    if (!isSame(a[i], b[i])) {
                        return false;
                    }
                }
                return true;
            }
            
            if (arrayCount || objectCount) {
                return false;
            }
    
            return a === b;
    
        }
    
    
    </script>
    <script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
    Login or Signup to reply.
  2. For sameness / equality comparison of JSON conform data structures where performance is important as well one might consider the following recursive implementation of 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 objectCount = [a, b].reduce((sum, item) => sum + (item.__proto__.constructor.name === 'Object' ? 1 : 0), 0);
        const arrayCount = objectCount ? 0 : [a, b].reduce((sum, item) => sum + (Array.isArray(item) ? 1 : 0), 0);
    
        if (arrayCount === 2 || objectCount === 2) {
          for (const i of arrayCount ? a.keys() : Object.keys(a)) {
            if (!isSame(a[i], b[i])) {
              return false;
            }
          }
          return true;
        }
        if (arrayCount || objectCount) {
          return false;
        }
        return a === b;
      }
    </script>
    <script benchmark data-count="10">
    
      const arrSession = 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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search