source

두 배열의 값이 동일한지 확인하는 방법

lovecheck 2023. 8. 30. 21:48
반응형

두 배열의 값이 동일한지 확인하는 방법

두 개의 어레이가 있습니다. 하나는 Ajax 요청의 정보로 채워져 있고 다른 하나는 사용자가 클릭하는 버튼을 저장합니다.다음 코드를 사용합니다(샘플 번호로 채웠습니다).

var array1 = [2, 4];
var array2 = [4, 2]; //It cames from the user button clicks, so it might be disordered.
array1.sort(); //Sorts both Ajax and user info.
array2.sort();
if (array1==array2) {
    doSomething();
}else{
    doAnotherThing();
}

하지만 그것은 항상 줍니다.false두 배열이 동일하지만 이름이 다른 경우에도 마찬가지입니다.(Chrome의 JS 콘솔에서 확인했습니다.)그렇다면 이 두 배열에 동일한 내용이 포함되어 있는지 알 수 있는 방법이 있습니까?왜 주는 거지?false첫 번째 배열에서 두 번째 배열에 없는 값을 어떻게 알 수 있습니까?

배열 항목이 개체가 아닌 경우(예: 숫자 또는 문자열인 경우), 결합된 문자열을 비교하여 어떤 순서로든 동일한 멤버를 가지고 있는지 확인할 수 있습니다.

var array1= [10, 6, 19, 16, 14, 15, 2, 9, 5, 3, 4, 13, 8, 7, 1, 12, 18, 11, 20, 17];
var array2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];

if(array1.sort().join(',')=== array2.sort().join(',')){
    alert('same members');
}
else alert('not a match');

두 어레이의 값이 동일한지 여부(각 값의 발생 횟수 및 순서에 관계없이)만 확인하려는 경우 lodash를 사용하여 이 작업을 수행할 수 있습니다.

_.isEmpty(_.xor(array1, array2))

짧고 간단하며 예쁜!

배열을 정렬하고 값을 하나씩 비교합니다.

function arrayCompare(_arr1, _arr2) {
    if (
      !Array.isArray(_arr1)
      || !Array.isArray(_arr2)
      || _arr1.length !== _arr2.length
      ) {
        return false;
      }
    
    // .concat() to not mutate arguments
    const arr1 = _arr1.concat().sort();
    const arr2 = _arr2.concat().sort();
    
    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
            return false;
         }
    }
    
    return true;
}

코드가 작동하지 않는 이유

의 경우, 자스크립어같레유경데우형의이터적,==그리고.===(「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 ==수행할 수 있음).즉, 그들은 확인합니다.arr1그리고.arr2메모리에 있는 동일한 개체입니다.이 예제에서는 두 배열이 같은 순서로 동일한 요소를 가지고 있지만 동일하지는 않습니다.

여기에 희망적으로 직관을 구축하는 예가 있습니다.false는 에대올바결니다입과른한▁for▁result에 대한 올바른 결과입니다.[1] === [1]:

const x = [1];
const y = [1];
x === y; // false
x[0] = 200;
console.log(x); // "Array [ 200 ]"
console.log(y); // "Array [ 1 ]"
x === y; // false

솔루션

개의 배열, 두개의배열,,arr1그리고.arr2다음과 같은 경우에만 동일한 구성원을 가집니다.

  • 에있는모것든에 있는 것.arr2안에 있습니다.arr1

그리고.

  • 에있는모것든에 있는 것.arr1안에 있습니다.arr2

이를 통해 다음과 같은 이점을 얻을 수 있습니다(ES2016).

const containsAll = (arr1, arr2) => 
                arr2.every(arr2Item => arr1.includes(arr2Item))
                
const sameMembers = (arr1, arr2) => 
                        containsAll(arr1, arr2) && containsAll(arr2, arr1);

sameMembers(arr1, arr2); // `true`

언더스코어를 사용하는 두 번째 솔루션은 다음과 같은 작업을 수행하려고 했습니다.

arr1.sort();
arr2.sort();

_.isEqual(arr1, arr2); // `true`

효과가 있는 이유는isEqual에서는 "딥 equality"를 확인합니다. 즉, 참조 equality 이상을 살펴보고 값을 비교합니다.

세 번째 질문에 대한 해결책

당신은 또한 어떤 것들을 찾는 방법을 물었습니다.arr1되지 않습니다.arr2.

이렇게 하면 됩니다(ES2015).

const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];

arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`

언더스코어의 : 방법을 사용할 수도 있습니다.

_.difference(arr1, arr2); // `[4]`

갱신하다

@을 참조하십시오.제은 @Redu 의참조십오시하견을의▁@▁. 내 솔루션은 다음과 같습니다.sameMembers에 두고 있는 은 하만당염두두에있고것은는이신지것은▁but▁have있입니다.sameMembersInOrder 도로알진려진▁also.deepEquals.

업데이트 2

어레이의 멤버 순서에 신경 쓰지 않는다면 ES2015+가 다음보다 더 나은 데이터 구조일 수 있습니다.Array위험한 원숭이 패치를 구현하고 사용하는 방법에 대한 MDN 참고 사항을 참조하십시오.

업데이트 3

순서가 상관없다면 그래도 세트를 사용하는 것이 좋습니다.그러나 어레이를 사용해야 하는 경우 이 솔루션은 앞서 설명한 솔루션보다 시간 복잡성이 더 높습니다.

function sameMembers(arr1, arr2) {
    const set1 = new Set(arr1);
    const set2 = new Set(arr2);
    return arr1.every(item => set2.has(item)) &&
        arr2.every(item => set1.has(item))
}
Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { //To test values in nested arrays
            if (!this[i].compare(testArr[i])) return false;
        }
        else if (this[i] !== testArr[i]) return false;
    }
    return true;
}

var array1 = [2, 4];
var array2 = [4, 2];
if(array1.sort().compare(array2.sort())) {
    doSomething();
} else {
    doAnotherThing();
}

아마?

우리의 목표는 기본적으로 두 어레이가 동일한 세트인지 확인하는 것입니다.집합은 수학적으로 정의된 집합입니다.가장 빠른 정렬은 점근적으로 O(nlog(n)) 시간이 걸립니다.따라서 배열을 정렬할 경우 최소 O(nlog(n)) 시간이 소요됩니다.그러나 사전 데이터 구조를 사용하면 이 작업을 더 빨리 수행할 수 있으므로 점근적으로 O(n) 시간(최악의 경우가 아닌 평균 시간)이 걸립니다.JS에서 사전은 단순히 키와 값이 있는 객체입니다.

/** assumes array elements are primitive types
* check whether 2 arrays are equal sets.
* @param  {} a1 is an array
* @param  {} a2 is an array
*/
function areArraysEqualSets(a1, a2) {
  const superSet = {};
  for (const i of a1) {
    const e = i + typeof i;
    superSet[e] = 1;
  }

  for (const i of a2) {
    const e = i + typeof i;
    if (!superSet[e]) {
      return false;
    }
    superSet[e] = 2;
  }

  for (let e in superSet) {
    if (superSet[e] === 1) {
      return false;
    }
  }

  return true;
}

이 함수는 원시 유형의 배열에서 작동하며 다음을 가정합니다.a1그리고.a2배열입니다.

이건 어때요?ES 2017은 다음과 같습니다.

const array1 = [1, 3, 5];
const array2 = [1, 5, 3];

const isEqual = (array1.length === array2.length) && (array1.every(val => array2.includes(val)));
console.log(isEqual);

첫 번째 조건은 두 배열의 길이가 동일한지 확인하고 두 번째 조건은 첫 번째 배열이 두 번째 배열의 하위 집합인지 확인합니다.이 두 조건을 결합하면 요소의 순서에 관계없이 두 배열의 모든 항목을 비교할 수 있습니다.

위의 코드는 두 배열 모두 중복되지 않는 항목이 있는 경우에만 작동합니다.

개체 동일성 검사:JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

위의 테스트는 http://www.w3schools.com/jsref/jsref_sort.asp 에서 문서화된 정렬 함수를 사용하는 객체 배열에서도 작동합니다.

플랫 JSON 스키마가 있는 소규모 어레이에 충분할 수 있습니다.

ES6의 경우

var array1 = [2, 4];
var array2 = [4, 2];


let difference = array1.filter(x => !array2.includes(x));

console.log("equals", difference?.length != 0 ? false : true)

이 두 배열을 비교할 때, 내용이 아니라 배열을 나타내는 개체를 비교하는 것입니다.

두 가지를 비교하려면 함수를 사용해야 합니다.길이가 동일한지 확인한 후에 하나를 반복해서 다른 하나와 비교하는 방식으로 작성할 수 있습니다.

나는 게임 프로젝트에서 단순한 정수 값을 가지고 있었습니다.
배열이 그대로 필요로 .
그래서 아래와 같이 했는데, 잘 작동했습니다. (여기에 붙여넣기 위해 편집된 코드)

var sourceArray = [1, 2, 3];
var targetArray = [3, 2, 1];

if (sourceArray.length !== targetArray.length) {
    // not equal
    // did something
    return false;
}

var newSortedSourceArray = sourceArray.slice().sort();
var newSortedTargetArray = targetArray.slice().sort();

if (newSortedSourceArray.toString() !== newSortedTargetArray.toString()) { // MAIN CHECK
    // not equal
    // did something
    return false;
}
else {
    // equal
    // did something
    // continued further below
}

// did some more work

return true;

도움이 되길 바랍니다.

ES6 사용

람다의 것을 사용하겠습니다.equals기능은 있지만 대신 로다쉬나 언더스코어를 사용할 수 있습니다.isEqual:

const R = require('ramda');

const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )

확산 반대자를 사용하여 원래 배열의 변형을 방지하고 순수한 기능을 유지합니다.

사용할 수 있습니다.reduce영리해 보이는 루프 대신 동료 개발자들이 당신을 똑똑한 사람으로 생각하게 하는 위험을 감수해야 합니다.

function isArrayContentSame(a, b) {
  if (Array.isArray(a) && Array.isArray(b) && a.length == b.length) {
    a = a.concat().sort()
    b = b.concat().sort()
    return a.reduce((acc,e,i) => acc && e === b[i], true)
  } else {
    return false;
  }
}

대부분의 다른 솔루션은 정렬, O(n*log n)를 사용하거나 라이브러리를 사용하거나 O(n^2) 복잡도를 가집니다.

선형 복잡도 O(n)인 순수 자바스크립트 솔루션은 다음과 같습니다.

/**
 * Check if two arrays of strings or numbers have the same values
 * @param {string[]|number[]} arr1
 * @param {string[]|number[]} arr2
 * @param {Object} [opts]
 * @param {boolean} [opts.enforceOrder] - By default (false), the order of the values in the arrays doesn't matter.
 * @return {boolean}
 */
function compareArrays(arr1, arr2, opts) {

  function vKey(i, v) {
    return (opts?.enforceOrder ? `${i}-` : '') + `${typeof v}-${v}`
  }

  if (arr1.length !== arr2.length) return false;

  const d1 = {};
  const d2 = {};  
  for (let i = arr1.length - 1; i >= 0; i--) {
    d1[vKey(i, arr1[i])] = true;
    d2[vKey(i, arr2[i])] = true;
  }
  
  for (let i = arr1.length - 1; i >= 0; i--) {
    const v = vKey(i, arr1[i]);
    if (d1[v] !== d2[v]) return false;
  }

  for (let i = arr2.length - 1; i >= 0; i--) {
    const v = vKey(i, arr2[i]);
    if (d1[v] !== d2[v]) return false;
  }

  return true
}

테스트:

arr1= [1, 2]
arr2= [1, 2]
compareArrays(arr1, arr2) => true
compareArrays(arr1, arr2, {enforceOrder: true}) => true
-------
arr1= [1, 2]
arr2= [2, 1]
compareArrays(arr1, arr2) => true
compareArrays(arr1, arr2, {enforceOrder: true}) => false
-------
arr1= [2, 1]
arr2= [1, 2]
compareArrays(arr1, arr2) => true
compareArrays(arr1, arr2, {enforceOrder: true}) => false
-------
arr1= [2, 2]
arr2= [1, 2]
compareArrays(arr1, arr2) => false
compareArrays(arr1, arr2, {enforceOrder: true}) => false
-------
arr1= [1, 2]
arr2= [1, 2, 3]
compareArrays(arr1, arr2) => false
compareArrays(arr1, arr2, {enforceOrder: true}) => false
-------
arr1= ["1"]
arr2= [1]
compareArrays(arr1, arr2) => false
compareArrays(arr1, arr2, {enforceOrder: true}) => false
-------
arr1= ["1", 2]
arr2= [2, "1"]
compareArrays(arr1, arr2) => true
compareArrays(arr1, arr2, {enforceOrder: true}) => false
-------
arr1= []
arr2= []
compareArrays(arr1, arr2) => true
compareArrays(arr1, arr2, {enforceOrder: true}) => true

당신은 성능에 대해 신경 쓰지 않는 것 같았고, 다른 어떤 대답도 신경 쓰지 않았습니다.

다음은 두 가지 모두에 대한 몇 가지 벤치마크입니다.sameArrayMembers (계속)[1,2,2] != [1,1,2]만 아니라 아라니만뿐라니▁)▁assameArrayMembersAsSet (계속)[1,2,2] == [1,1,2])

확인하지 않았습니다.[1,1,2]과 같은[1,2]길이를 확인하지 않는 것보다 세트를 확인하는 것을 주장한다면 아마도 제가 주어야 할 것입니다.

const tests = {
  'Maciej Krawczyk': (_arr1, _arr2) => {

    if (!Array.isArray(_arr1) || ! Array.isArray(_arr2) || _arr1.length !== _arr2.length)
      return false;

    var arr1 = _arr1.concat().sort();
    var arr2 = _arr2.concat().sort();

    for (var i = 0; i < arr1.length; i++) {

        if (arr1[i] !== arr2[i])
            return false;

    }

    return true;
  },
  'canbax': (a1, a2) => {
    const superSet = {};
    for (const i of a1) {
      const e = i + typeof i;
      superSet[e] = 1;
    }

    for (const i of a2) {
      const e = i + typeof i;
      if (!superSet[e]) {
        return false;
      }
      superSet[e] = 2;
    }

    for (let e in superSet) {
      if (superSet[e] === 1) {
        return false;
      }
    }

    return true;
  },
  'kennebec': (array1, array2) => {
    return array1.slice().sort().join(',')=== array2.slice().sort().join(',');
  },
  'Max Heiber': function() {
    const containsAll = (arr1, arr2) => 
        arr2.every(arr2Item => arr1.includes(arr2Item));
    return (arr1, arr2) => 
        containsAll(arr1, arr2) && containsAll(arr2, arr1);
  }(),
  'gman': (a, b) => {
    if (a.length !== b.length) { return false; }
    const counts = new Map();
    for (const v of a) {
      const count = counts.get(v) || 0;
      counts.set(v, count + 1);
    }
    for (const v of b) {
      const count = counts.get(v);
      if (!count) {   // undefined or 0, both mean arrays are not the same
        return false;
      }
      counts.set(v, count - 1);
    }
    return true;
  },
  'Bemmu': (a, b) => {
    if (Array.isArray(a) && Array.isArray(b) && a.length == b.length) {
      a = a.concat().sort()
      b = b.concat().sort()
      return a.reduce((acc,e,i) => acc && e === b[i], true)
    } else {
      return false;
    }
  },
  'Sandeep': (array1, array2) => {
    return JSON.stringify(array1.sort()) === JSON.stringify(array2.sort());
  },
  'camslice': (arr1, arr2) => {
    const arr1test = arr1.slice().sort();
    const arr2test = arr2.slice().sort();
    return !arr1test.some((val, idx) => val !== arr2test[idx]);
  },
  'Dimitrios Stefos': (arr1, arr2) => {
    if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length!=arr2.length)
        return false;

    return arr1.length==arr1.filter(word => arr2.includes(word)).length;
  },
  'SC1000': (arr1, arr2, opts) => {
    function vKey(i, v) {
      return (opts?.enforceOrder ? `${i}-` : '') + `${typeof v}-${v}`
    }

    if (arr1.length !== arr2.length) return false;

    const d1 = {};
    const d2 = {};  
    for (let i = arr1.length - 1; i >= 0; i--) {
      d1[vKey(i, arr1[i])] = true;
      d2[vKey(i, arr2[i])] = true;
    }

    for (let i = arr1.length - 1; i >= 0; i--) {
      const v = vKey(i, arr1[i]);
      if (d1[v] !== d2[v]) return false;
    }

    for (let i = arr2.length - 1; i >= 0; i--) {
      const v = vKey(i, arr2[i]);
      if (d1[v] !== d2[v]) return false;
    }

    return true
  },
  'Magnus Fohlström': (arr1, arr2) => {
        let count = (arr, val) => arr.reduce((count, curr) => (curr === val ? 1:0) + count, 0);
        return arr1.length === arr2.length && arr1.reduce((checks, val) =>
            checks.concat(count(arr1, val) === count(arr2, val)), []).every(check => check);
   },
};

// ----------------------------

function createExposedPromise() {
 const p = {};
 p.promise = new Promise((resolve, reject) => {
   p.resolve = resolve;
   p.reject = reject;
 });
 return p;
}

function assert(cond) {
  if (!cond) {
    log('assert');
    throw new Error();
  }
}

async function main() {
  await testResults(true, 'sameArrayMembers');
  await testResults(false, 'sameArrayMemembersAsSet');
  
  async function testResults(asSet, msg) {
    log(`\n=======[ ${msg} ] ============`);
    const suite = new Benchmark.Suite();
    let test;

    // reject if they fail simple test
    const a = [1,1,2];
    const b = [1,2,2];
    for (const [name, fn] of Object.entries(tests)) {
      if (fn(a, b) === asSet) {
        log(`${name} fails for ${msg}([${a}], [${b}])`);
      } else {    
        suite.add(name, () => test(fn));
      }
    }

    let endPromise;

    suite.on('cycle', event => log(String(event.target)));
    suite.on('complete', function() {
      log('Fastest is ' + this.filter('fastest').map('name'));
      endPromise.resolve();
    });

    async function runWith(num, title) {
      log(`------[ ${title} ] -----------`);

      const a = [];
      for (let i = 0; i < num; ++i) {
        a[i] = Math.random();
      }
      const b = [...a];
      const c = [...a]; c[c.length / 2 | 0]++;

      endPromise = createExposedPromise();

      test = (fn) => {
        assert(fn(a, b))
        assert(!fn(a, c));
      };

      suite.reset();
      suite.run({'async': true});
      await endPromise.promise;
    }

    await runWith(10, 'small (10)');
    await runWith(100, 'medium (100)');
    await runWith(10000, 'large (10000)');
  }
}
main();

function log(...args) {
  const elem = document.createElement('pre');
  elem.textContent = args.join(' ');
  document.body.appendChild(elem);
}
pre { margin: 0; }
<script src="https://unpkg.com/lodash@4.17.20/lodash.js"></script>
<script src="https://unpkg.com/benchmark@2.1.4/benchmark.js"></script>

JS 엔진이 업데이트되기 때문에 결과는 아마도 시간이 지남에 따라 달라질 것입니다.다음은 2020/09/28의 몇 가지 결과입니다.

크롬 87

=======[ sameArrayMembers ] ============
canbax fails for sameArrayMembers([1,1,2], [1,2,2])
Max Heiber fails for sameArrayMembers([1,1,2], [1,2,2])
Dimitrios Stefos fails for sameArrayMembers([1,1,2], [1,2,2])
SC1000 fails for sameArrayMembers([1,1,2], [1,2,2])
------[ small (10) ] -----------
Maciej Krawczyk x 246,129 ops/sec ±0.84% (66 runs sampled)
kennebec x 182,234 ops/sec ±0.56% (64 runs sampled)
gman x 377,356 ops/sec ±1.55% (64 runs sampled)
Bemmu x 244,850 ops/sec ±0.76% (64 runs sampled)
Sandeep x 100,529 ops/sec ±1.53% (63 runs sampled)
camslice x 542,577 ops/sec ±0.68% (64 runs sampled)
Fastest is camslice
------[ medium (100) ] -----------
Maciej Krawczyk x 12,121 ops/sec ±1.40% (63 runs sampled)
kennebec x 10,219 ops/sec ±1.60% (63 runs sampled)
gman x 41,225 ops/sec ±1.63% (62 runs sampled)
Bemmu x 12,400 ops/sec ±1.10% (63 runs sampled)
Sandeep x 12,470 ops/sec ±0.50% (64 runs sampled)
camslice x 57,126 ops/sec ±0.54% (64 runs sampled)
Fastest is camslice
------[ large (10000) ] -----------
Maciej Krawczyk x 30.75 ops/sec ±0.86% (42 runs sampled)
kennebec x 27.35 ops/sec ±1.11% (38 runs sampled)
gman x 376 ops/sec ±0.46% (62 runs sampled)
Bemmu x 30.91 ops/sec ±0.77% (42 runs sampled)
Sandeep x 80.33 ops/sec ±0.54% (53 runs sampled)
camslice x 166 ops/sec ±0.44% (61 runs sampled)
Fastest is gman

=======[ sameArrayMemembersAsSet ] ============
Maciej Krawczyk fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
kennebec fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
gman fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
Bemmu fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
Sandeep fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
camslice fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
------[ small (10) ] -----------
canbax x 110,826 ops/sec ±2.07% (63 runs sampled)
Max Heiber x 2,699,807 ops/sec ±1.31% (63 runs sampled)
Dimitrios Stefos x 2,910,096 ops/sec ±0.65% (62 runs sampled)
SC1000 x 59,989 ops/sec ±2.61% (63 runs sampled)
Fastest is Dimitrios Stefos
------[ medium (100) ] -----------
canbax x 9,624 ops/sec ±2.20% (53 runs sampled)
Max Heiber x 88,945 ops/sec ±0.71% (64 runs sampled)
Dimitrios Stefos x 94,425 ops/sec ±0.51% (65 runs sampled)
SC1000 x 5,742 ops/sec ±0.74% (33 runs sampled)
Fastest is Dimitrios Stefos
------[ large (10000) ] -----------
canbax x 59.85 ops/sec ±1.69% (46 runs sampled)
Max Heiber x 13.50 ops/sec ±0.87% (26 runs sampled)
Dimitrios Stefos x 15.40 ops/sec ±0.89% (30 runs sampled)
SC1000 x 37.42 ops/sec ±1.47% (40 runs sampled)
Fastest is canbax

파이어폭스 80

=======[ sameArrayMembers ] ============
canbax fails for sameArrayMembers([1,1,2], [1,2,2])
Max Heiber fails for sameArrayMembers([1,1,2], [1,2,2])
Dimitrios Stefos fails for sameArrayMembers([1,1,2], [1,2,2])
SC1000 fails for sameArrayMembers([1,1,2], [1,2,2])
------[ small (10) ] -----------
Maciej Krawczyk x 118,391 ops/sec ±0.52% (65 runs sampled)
kennebec x 70,254 ops/sec ±0.40% (67 runs sampled)
gman x 201,659 ops/sec ±3.23% (57 runs sampled)
Bemmu x 118,133 ops/sec ±0.67% (64 runs sampled)
Sandeep x 69,484 ops/sec ±1.40% (65 runs sampled)
camslice x 130,443 ops/sec ±0.55% (65 runs sampled)
Fastest is gman
------[ medium (100) ] -----------
Maciej Krawczyk x 11,418 ops/sec ±2.81% (61 runs sampled)
kennebec x 7,278 ops/sec ±1.37% (41 runs sampled)
gman x 19,748 ops/sec ±6.60% (53 runs sampled)
Bemmu x 11,535 ops/sec ±1.09% (62 runs sampled)
Sandeep x 8,234 ops/sec ±1.46% (45 runs sampled)
camslice x 14,277 ops/sec ±3.08% (60 runs sampled)
Fastest is gman
------[ large (10000) ] -----------
Maciej Krawczyk x 65.25 ops/sec ±2.13% (49 runs sampled)
kennebec x 47.73 ops/sec ±0.82% (51 runs sampled)
gman x 210 ops/sec ±3.54% (54 runs sampled)
Bemmu x 66.90 ops/sec ±0.53% (50 runs sampled)
Sandeep x 63.13 ops/sec ±1.59% (48 runs sampled)
camslice x 115 ops/sec ±1.36% (56 runs sampled)
Fastest is gman

=======[ sameArrayMemembersAsSet ] ============
Maciej Krawczyk fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
kennebec fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
gman fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
Bemmu fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
Sandeep fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
camslice fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
------[ small (10) ] -----------
canbax x 79,433 ops/sec ±1.11% (57 runs sampled)
Max Heiber x 1,822,200 ops/sec ±0.92% (65 runs sampled)
Dimitrios Stefos x 2,258,820 ops/sec ±0.48% (65 runs sampled)
SC1000 x 35,784 ops/sec ±1.42% (63 runs sampled)
Fastest is Dimitrios Stefos
------[ medium (100) ] -----------
canbax x 6,726 ops/sec ±0.60% (38 runs sampled)
Max Heiber x 41,620 ops/sec ±1.08% (65 runs sampled)
Dimitrios Stefos x 53,041 ops/sec ±1.61% (64 runs sampled)
SC1000 x 3,450 ops/sec ±0.56% (64 runs sampled)
Fastest is Dimitrios Stefos
------[ large (10000) ] -----------
canbax x 44.18 ops/sec ±5.87% (42 runs sampled)
Max Heiber x 5.62 ops/sec ±4.79% (19 runs sampled)
Dimitrios Stefos x 6.77 ops/sec ±1.21% (21 runs sampled)
SC1000 x 24.18 ops/sec ±3.50% (36 runs sampled)
Fastest is canbax

사파리 14

=======[ sameArrayMembers ] ============
canbax fails for sameArrayMembers([1,1,2], [1,2,2])
Max Heiber fails for sameArrayMembers([1,1,2], [1,2,2])
Dimitrios Stefos fails for sameArrayMembers([1,1,2], [1,2,2])
SC1000 fails for sameArrayMembers([1,1,2], [1,2,2])
------[ small (10) ] -----------
Maciej Krawczyk x 142,798 ops/sec ±0.50% (65 runs sampled)
kennebec x 118,073 ops/sec ±1.12% (63 runs sampled)
gman x 760,109 ops/sec ±0.46% (66 runs sampled)
Bemmu x 136,265 ops/sec ±0.48% (63 runs sampled)
Sandeep x 69,868 ops/sec ±0.44% (64 runs sampled)
camslice x 155,548 ops/sec ±0.45% (64 runs sampled)
Fastest is gman
------[ medium (100) ] -----------
Maciej Krawczyk x 8,479 ops/sec ±0.52% (46 runs sampled)
kennebec x 5,992 ops/sec ±2.54% (34 runs sampled)
gman x 83,390 ops/sec ±0.37% (64 runs sampled)
Bemmu x 8,615 ops/sec ±0.56% (63 runs sampled)
Sandeep x 5,943 ops/sec ±0.67% (64 runs sampled)
camslice x 8,753 ops/sec ±0.45% (47 runs sampled)
Fastest is gman
------[ large (10000) ] -----------
Maciej Krawczyk x 62.66 ops/sec ±0.87% (51 runs sampled)
kennebec x 46.46 ops/sec ±0.66% (48 runs sampled)
gman x 615 ops/sec ±2.33% (60 runs sampled)
Bemmu x 60.98 ops/sec ±1.28% (52 runs sampled)
Sandeep x 49.11 ops/sec ±2.07% (47 runs sampled)
camslice x 66.33 ops/sec ±4.44% (50 runs sampled)
Fastest is gman

=======[ sameArrayMemembersAsSet ] ============
Maciej Krawczyk fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
kennebec fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
gman fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
Bemmu fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
Sandeep fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
camslice fails for sameArrayMemembersAsSet([1,1,2], [1,2,2])
------[ small (10) ] -----------
canbax x 167,041 ops/sec ±0.63% (64 runs sampled)
Max Heiber x 1,281,054 ops/sec ±0.74% (59 runs sampled)
Dimitrios Stefos x 1,127,639 ops/sec ±0.98% (64 runs sampled)
SC1000 x 112,824 ops/sec ±0.37% (64 runs sampled)
Fastest is Max Heiber
------[ medium (100) ] -----------
canbax x 8,784 ops/sec ±0.53% (47 runs sampled)
Max Heiber x 37,824 ops/sec ±0.52% (65 runs sampled)
Dimitrios Stefos x 41,238 ops/sec ±0.85% (63 runs sampled)
SC1000 x 6,181 ops/sec ±0.61% (35 runs sampled)
Fastest is Dimitrios Stefos
------[ large (10000) ] -----------
canbax x 63.83 ops/sec ±2.46% (49 runs sampled)
Max Heiber x 5.41 ops/sec ±0.52% (18 runs sampled)
Dimitrios Stefos x 6.02 ops/sec ±1.32% (19 runs sampled)
SC1000 x 42.25 ops/sec ±1.45% (45 runs sampled)
Fastest is canbax

또 다른 한 줄 솔루션:

array1.concat(array2).filter((item, index, currentArr) => currentArr.lastIndexOf(item) == currentArr.indexOf(item)).length == 0;

또는

[...array1, ...array2].filter((item, index, currentArr) => currentArr.lastIndexOf(item) == currentArr.indexOf(item)).length == 0;
  1. 두 배열의 값이 동일하지만 순서가 같을 수 있는지 확인합니다.

function compareArr(arr1, arr2) {
  return arr1.sort().join(',') == arr2.sort().join(',');
}

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

  1. 두 배열의 값이 같고 순서가 같은지 확인합니다(단, 정렬하지 마십시오).

function compareArrOrder(arr1, arr2) {
  return arr1.join(',') == arr2.join(',');
}

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

오랜만에 대답하지만 이것이 간단한 해결책과 현대적인 신인을 찾는 사람에게 도움이 되기를 바랍니다.

이제 우리는 다음과 같은 여러 라이브러리를 사용하여 이를 달성할 수 있습니다.lodash,underscore등(간단함, 다양한 기능 및 높은 사용률로 인해 오늘날 프로젝트의 일부가 됨)

당신은 lodash 라이브러리의 교차로를 이용할 수 있습니다.

_.intersection(['2-1', '1'], ['2-2', '3-1', '2-1']); 
// => ['2-1']

이것은 모든 데이터 유형에 적용됩니다.

사용해 보세요.

function arraysEqual(arr1, arr2){
    if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length!=arr2.length)
        return false;

    return arr1.length==arr1.filter(word => arr2.includes(word)).length;
}

코드 & 설명

function arrayEquals(arr1, arr2) {
  // compare array lengths, if not equal then skip.
  if (arr1.length !== arr2.length) return false;

  // setup a variable of the array length
  let i = arr1.length;

  // iterate through every element in arr1 basically...
  while (i--) {
    // if arr2 doesn't include x element from arr1, return false
    if (!arr2.includes(arr1[i])) return false;

    // passes tests and checks out
  };
  return true;
}

// works with multiple types
let foo = ["foo", "bar", 1, 2, true];
let bar = ["bar", 2, true, "foo", 1];

console.log(foo,bar,"Should return true: " + arrayEquals(foo, bar));

let fob = ["bar", "foo"];
let oar = ["oar", "foo"];

console.log(fob,oar,"Should return false (bar ≠ oar): " + arrayEquals(fob, oar));

부인

이것은 문자열, 숫자, 부울 등과 같은 간단한 유형만 지원합니다.코드를 재귀적으로 편집하지 않는 한 개체나 배열을 자세히 들여다 볼 수는 없지만, 질문에 대한 답변 자체에서는 문제가 없는 것 같습니다.당신이 숫자를 제공했으니 제 답변은 숫자와 함께 작동할 것입니다.

ES6를 사용한 얕은 동등성을 위한 간단한 솔루션:

const arr1test = arr1.slice().sort()
const arr2test = arr2.slice().sort()
const equal = !arr1test.some((val, idx) => val !== arr2test[idx])

각 배열의 얕은 복사본을 만들고 정렬합니다. 다음 그면사용을 합니다.some()환하다순을 arr1test각을 각, 값의 합니다.arr2test같은 색인으로.같다면, 모든값같다면이,면,some()아온다를 합니다.false 차례로 리고그차례로차▁and로.equal으로 됩니다.true.

사용할 수도 있습니다.every()하지만 그것은 배열의 모든 요소를 순환해야 만족할 수 있습니다.true 반면에, 면에는, 과결반.some()동일하지 않은 값을 발견하는 즉시 보석됩니다.

const equal = arr1test.every((val, idx) => val === arr2test[idx])

결과를 얻는 가장 쉬운 방법은 아래와 같습니다.

const array1 = [1,2,3,4]

const array2 = [3,4,5,6]

const result = array1.filter(arr => array2.includes(arr))

console.log(result)

프로토타입 프레임워크를 사용하는 경우 배열의 교차 방법을 사용하여 배열이 동일한지 확인할 수 있습니다(순서에 관계없이).

var array1 = [1,2];
var array2 = [2,1];

if(array1.intersect(array2).length === array1.length) {
    alert("arrays are the same!");
}

이 답변을 확인해 주십시오.

var arr1= [12,18];
var arr2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
for(i=0;i<arr1.length;i++)
{
var array1=arr1[i];
for(j=0;j<arr2.length;j++)
{
    var array2=arr2[j];
    if(array1==array2)
    {
return true;
    }
}
}

저는 수락된 답변을 바탕으로 다른 방법이 있습니다.

function compareArrays(array1, array2) {

    if (
        !Array.isArray(array1)
        || !Array.isArray(array2)
        || array1.length !== array2.length
    ) return false;

    var first = array1.sort().map(value => (String(value))).join();
    var second = array2.sort().map(value => (String(value))).join();

    return first == second ? true : false;
}

두 배열을 비교하여 두 배열이 동일한 요소를 가지고 있는지 확인하는 기능입니다.고장이 나더라도...

단순한 배열에 적합합니다.[문자열, 숫자, 부울, 늘, NaN].

.sort()를 사용하지 않고 원래 배열을 수정합니다.어떤 사람들은 그게 나쁘다고 말합니다...

주의.이 기능은 개체 "[], {}" 또는 이러한 배열 내의 함수를 비교할 수 없으므로 제한됩니다. 배열 자체가 개체입니다.

   let arraysHasSameElements = (arr1, arr2) => {
        let count =
            // returns counting of occurrences.
            (arr, val) => arr.reduce((count, curr) => (curr === val ? 1 : 0) + count, 0);

        /* this will return true if lengths of the arrays is equal.
           then compare them.*/
        return arr1.length === arr2.length

            // compare arr1 against arr2.
            && arr1.reduce((checks, val) =>

                /*  creating array of checking if a value has equal amount of occurrences
                    in both arrays, then adds true 'check'. */
                checks.concat(count(arr1, val) === count(arr2, val)), [])

                // checking if each check is equal to true, then .every() returns true.
                .every(check => check);
    }

    let arr1 = ['',-99,true,NaN,21,null,false,'help',-99,'help',NaN], 
        arr2 = [null,-99,'',NaN,NaN,false,true,-99,'help',21,'help'];
    arraysHasSameElements(arr1, arr2); //true

    let arr3 = [false,false,false,false,false,false], 
        arr4 = [false,false,false,false,false,false]
    arraysHasSameElements(arr3, arr4); //true


    // here we have uncommented version.
    let arraysHasSameElements = (arr1, arr2) => {
        let count = (arr, val) => arr.reduce((count, curr) => (curr === val ? 1:0) + count, 0);
        return arr1.length === arr2.length && arr1.reduce((checks, val) =>
            checks.concat(count(arr1, val) === count(arr2, val)), []).every(check => check);
    }

원시 값만 테스트하려는 경우 다음을 시도할 수 있습니다.

if(JSON.stringify(arr1.sort()) !== JSON.stringify(arr2.sort())) {
  console.log('invalid');
}

이것은 나에게 잘 먹혔지만, 나는 왜 어떤 사람들이 어레이에서 concat 방법을 사용하는지 이해할 수 없습니다.

/**
 * 
 * @param {Array} firstArray 
 * @param {Array} secondArray 
 * @returns {boolean}
 */
function arrayIsEqual(firstArray, secondArray)
{
    if (
        !Array.isArray(firstArray) 
        || !Array.isArray(secondArray) 
        || firstArray.length !== secondArray.length
    ) {
        console.log('Bad params!\n');
        return false;
    }
    $bool = firstArray === secondArray || firstArray.every((x,i)=> Array.isArray(x) ? arrayIsEqual(x, secondArray[i]) : x === secondArray[i]);
    console.log($bool);
    return $bool;
}

let a = [1, 2];
let b = [3, 4];
let c = "Me and you";
let d = [1, [2, 3, 5], 4];
let e = [1, [2, 3, 5], 4];
let f = [1, [2, 3, 5], [4]];
let g = [1, [2, 3, 5], [4]];

arrayIsEqual(a, b);
arrayIsEqual(b, c);
arrayIsEqual(c, a);
arrayIsEqual(a, a);
arrayIsEqual(d, e);
arrayIsEqual(e, f);
arrayIsEqual(e, e);
arrayIsEqual(g, f);

산출량

false
Bad params!

Bad params!

true
true
true
true
false
true
true
true
true

배열 요소의 순서가 중요하지 않은 경우에는

function arraysEqual<T>(a:T[], b:T[]) {
  if (a === b) return true;
  if (a == null || b == null) return false;
  if (a.length !== b.length) return false;


  const aClone = [...a].sort();
  const bClone = [...b].sort();
  for (var i = 0; i < aClone.length; ++i) {
    if (aClone[i] !== bClone[i]) return false;
  }
  return true;
}

const arr1 = [1,2,3,4];
const arr2 = [3,2,1,4];
console.log(arraysEqual(arr1, arr2)) //true

해석

질문이 약간 애매하지만, 다음과 같이 해석하겠습니다.

1차원 배열 B가 배열 A의 혼합 버전인지 감지하는 함수를 어떻게 작성할 수 있습니까?

따라서:

  1. 용사를 합니다.includes()A가 B의 모든 값을 "포함"하고 그 반대인지 확인해야 할 뿐만 아니라 각 항목의 발생 횟수가 배열 간에도 동일한지 확인해야 하기 때문에 작동하지 않습니다.를 들어, 예들어, 사용을 합니다.includes()이러한 배열의 논리는 거짓 양의 결과를 초래합니다.
A: [true, false, true]
B: [true, true, false]

A와 B는 길이가 같고 A는 B의 모든 품목을 포함하고 그 반대도 마찬가지입니다.하지만 분명히 B는 A의 개편이 아닙니다.

  1. 는 자바스크립트의 네이티브 자바스크립트 을 할 수 .SetSet반복되는 값을 제거합니다.

의사코드

assert typeof A1 and A2 === Array
assert A1 length = A2 length

for each element E of A1:
  delete E from A2
  
return true if A2 is empty

설명.

허락하다A그리고.B두 목록입니다.

사례 1

A그리고.B길이가 다릅니다. 아다가false긴 목록에는 짧은 목록에 존재하지 않는 요소가 있어야 하기 때문입니다.

사례 2

A그리고.B 길가같고이,,B는 의개니다입의 개편입니다.A 원소에 eA에 그수 를빼다에서 카운트를 .B정확히 그것의 발생 횟수만큼.A.Bempty를 합니다. 반환합니다.true.

사례 3

A그리고.B 요소의 는 같습니다.xB 요개 수보작습다의 보다 작습니다.xA.ㅠㅠ A그리고.B, 또 요.y에 있어서 누구의 것인지.A보다 .y의 카운트는 서에중요입니다B 원소에 eA에 그수 를빼다에서 카운트를 .B정확히 그것의 발생 횟수만큼.A에.y에 있어서 누구의 것인지.A보다 .y는 B, B 계면하산로,B남은 개수의 값은 항상 하나 이상입니다. 아다가false.

구현 세부 정보

내 구현은 Mnemonist 패키지의 MultiSet 데이터 구조에 따라 달라집니다.이것은 특별한 유형의Set중복 값을 사용할 수 있습니다.이 어레이에서 .Set.

구현 코드

const MultiSet = require('mnemonist/multi-set');

export const arraysHaveSameValues = <T> (a1: Array<T>, a2: Array<T>): boolean => {
  if (!Array.isArray(a1) || !Array.isArray(a2)) return undefined;
  else if (a1.length !== a2.length) return false;
  else {
    const s2 = MultiSet.from(a2);
    const deleteFromS2 = (x) => s2.remove(x);
    a1.forEach(deleteFromS2);
    return s2.size === 0;
  }
};

언급URL : https://stackoverflow.com/questions/6229197/how-to-know-if-two-arrays-have-the-same-values

반응형