itsource

javascript에서 배열 교차점에 대한 가장 간단한 코드

mycopycode 2022. 11. 5. 17:28
반응형

javascript에서 배열 교차점에 대한 가장 간단한 코드

Javascript에서 어레이 교차로를 구현하기 위한 가장 간단한 라이브러리가 필요 없는 코드는 무엇입니까?쓰고 싶다

intersection([1,2,3], [2,3,4,5])

취득하다

[2, 3]

와 의 조합을 사용합니다.

const filteredArray = array1.filter(value => array2.includes(value));

이전 브라우저의 경우 화살표 기능이 있거나 없는 경우:

var filteredArray = array1.filter(function(n) {
    return array2.indexOf(n) !== -1;
});

둘 다 NB! 둘다 다다.includes ★★★★★★★★★★★★★★★★★」.indexOf는 배열 를 내부적으로 합니다.===따라서 배열에 객체가 포함되어 있는 경우 객체 참조만 비교합니다(내용은 비교되지 않습니다).자체 비교 로직을 지정하려면 대신 을 사용하십시오.

특히 입력이 정렬되었다고 가정할 수 있는 경우에는 파괴가 가장 간단해 보입니다.

/* destructively finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *  State of input arrays is undefined when
 *  the function returns.  They should be 
 *  (prolly) be dumped.
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length, b.length)
 */
function intersection_destructive(a, b)
{
  var result = [];
  while( a.length > 0 && b.length > 0 )
  {  
     if      (a[0] < b[0] ){ a.shift(); }
     else if (a[0] > b[0] ){ b.shift(); }
     else /* they're equal */
     {
       result.push(a.shift());
       b.shift();
     }
  }

  return result;
}

비파괴는 머리카락이 더 복잡해야 합니다. 지수를 추적해야 하기 때문입니다.

/* finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length(), b.length())
 */
function intersect_safe(a, b)
{
  var ai=0, bi=0;
  var result = [];

  while( ai < a.length && bi < b.length )
  {
     if      (a[ai] < b[bi] ){ ai++; }
     else if (a[ai] > b[bi] ){ bi++; }
     else /* they're equal */
     {
       result.push(a[ai]);
       ai++;
       bi++;
     }
  }

  return result;
}

사용 환경에서 ECMAScript 6 Set을 지원하는 경우 다음과 같은 단순하고 효율적인 방법(사양 링크 참조)이 있습니다.

function intersect(a, b) {
  var setA = new Set(a);
  var setB = new Set(b);
  var intersection = new Set([...setA].filter(x => setB.has(x)));
  return Array.from(intersection);
}

짧지만 교차로( 추가 교차로 )Set

function intersect(a, b) {
  var setB = new Set(b);
  return [...new Set(a)].filter(x => setB.has(x));
}

해 주십시오.new Set([1, 2, 3, 3]).size3.

Underscore.js 또는 lodash.js 사용

_.intersection( [0,345,324] , [1,0,324] )  // gives [0,324]

// Return elements of array a that are also in b in linear time:
function intersect(a, b) {
  return a.filter(Set.prototype.has, new Set(b));
}

// Example:
console.log(intersect([1,2,3], [2,3,4,5]));

나는 대량의 입력에서 다른 구현보다 뛰어난 위의 간결한 솔루션을 추천한다.작은 입력의 퍼포먼스가 중요한 경우는, 다음의 대체 방법을 확인해 주세요.

대안 및 성능 비교:

대체 구현에 대해서는 다음 스니펫을 참조하고 성능 비교에 대해서는 https://jsperf.com/array-intersection-comparison을 확인하십시오.

function intersect_for(a, b) {
  const result = [];
  const alen = a.length;
  const blen = b.length;
  for (let i = 0; i < alen; ++i) {
    const ai = a[i];
    for (let j = 0; j < blen; ++j) {
      if (ai === b[j]) {
        result.push(ai);
        break;
      }
    }
  } 
  return result;
}

function intersect_filter_indexOf(a, b) {
  return a.filter(el => b.indexOf(el) !== -1);
}

function intersect_filter_in(a, b) {
  const map = b.reduce((map, el) => {map[el] = true; return map}, {});
  return a.filter(el => el in map);
}

function intersect_for_in(a, b) {
  const result = [];
  const map = {};
  for (let i = 0, length = b.length; i < length; ++i) {
    map[b[i]] = true;
  }
  for (let i = 0, length = a.length; i < length; ++i) {
    if (a[i] in map) result.push(a[i]);
  }
  return result;
}

function intersect_filter_includes(a, b) {
  return a.filter(el => b.includes(el));
}

function intersect_filter_has_this(a, b) {
  return a.filter(Set.prototype.has, new Set(b));
}

function intersect_filter_has_arrow(a, b) {
  const set = new Set(b);
  return a.filter(el => set.has(el));
}

function intersect_for_has(a, b) {
  const result = [];
  const set = new Set(b);
  for (let i = 0, length = a.length; i < length; ++i) {
    if (set.has(a[i])) result.push(a[i]);
  }
  return result;
}

파이어폭스 53에서의 결과:

  • 대규모 어레이에서의 ops/초 (10,000 요소):

    filter + has (this)               523 (this answer)
    for + has                         482
    for-loop + in                     279
    filter + in                       242
    for-loops                          24
    filter + includes                  14
    filter + indexOf                   10
    
  • 스몰 어레이(100 요소):

    for-loop + in                 384,426
    filter + in                   192,066
    for-loops                     159,137
    filter + includes             104,068
    filter + indexOf               71,598
    filter + has (this)            43,531 (this answer)
    filter + has (arrow function)  35,588
    

ES6 용어로 나의 공헌.일반적으로 이 명령어는 인수로 제공된 배열의 수가 무한히 많은 배열의 교차를 찾습니다.

Array.prototype.intersect = function(...a) {
  return [this,...a].reduce((p,c) => p.filter(e => c.includes(e)));
}
var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]],
     arr = [0,1,2,3,4,5,6,7,8,9];

document.write("<pre>" + JSON.stringify(arr.intersect(...arrs)) + "</pre>");

어소시에이션 어레이를 사용하면 어떨까요?

function intersect(a, b) {
    var d1 = {};
    var d2 = {};
    var results = [];
    for (var i = 0; i < a.length; i++) {
        d1[a[i]] = true;
    }
    for (var j = 0; j < b.length; j++) {
        d2[b[j]] = true;
    }
    for (var k in d1) {
        if (d2[k]) 
            results.push(k);
    }
    return results;
}

편집:

// new version
function intersect(a, b) {
    var d = {};
    var results = [];
    for (var i = 0; i < b.length; i++) {
        d[b[i]] = true;
    }
    for (var j = 0; j < a.length; j++) {
        if (d[a[j]]) 
            results.push(a[j]);
    }
    return results;
}

여러 어레이를 교차시키는 처리를 해야 하는 경우:

const intersect = (a1, a2, ...rest) => {
  const a12 = a1.filter(value => a2.includes(value))
  if (rest.length === 0) { return a12; }
  return intersect(a12, ...rest);
};

console.log(intersect([1,2,3,4,5], [1,2], [1, 2, 3,4,5], [2, 10, 1])) 

  1. 분류하다
  2. 인덱스 0에서 하나씩 체크하고 거기서 새 배열을 만듭니다.

이런 거. 근데 테스트는 잘 안 돼.

function intersection(x,y){
 x.sort();y.sort();
 var i=j=0;ret=[];
 while(i<x.length && j<y.length){
  if(x[i]<y[j])i++;
  else if(y[j]<x[i])j++;
  else {
   ret.push(x[i]);
   i++,j++;
  }
 }
 return ret;
}

alert(intersection([1,2,3], [2,3,4,5]));

PS: 이 알고리즘은 숫자와 일반 문자열, 임의 객체 배열의 교차점만을 대상으로 합니다.

원시 요소의 정렬된 배열에 대한 @atk 구현의 성능은 .shift가 아닌 .pop을 사용하여 개선할 수 있습니다.

function intersect(array1, array2) {
   var result = [];
   // Don't destroy the original arrays
   var a = array1.slice(0);
   var b = array2.slice(0);
   var aLast = a.length - 1;
   var bLast = b.length - 1;
   while (aLast >= 0 && bLast >= 0) {
      if (a[aLast] > b[bLast] ) {
         a.pop();
         aLast--;
      } else if (a[aLast] < b[bLast] ){
         b.pop();
         bLast--;
      } else /* they're equal */ {
         result.push(a.pop());
         b.pop();
         aLast--;
         bLast--;
      }
   }
   return result;
}

jsPerf: http://bit.ly/P9FrZK를 사용하여 벤치마크를 작성했습니다..pop을 사용하는 것이 약 3배 빠릅니다.

jQuery 사용:

var a = [1,2,3];
var b = [2,3,4,5];
var c = $(b).not($(b).not(a));
alert(c);

여기서 가장 작은 것(필터/indexOf 솔루션)을 조금만 수정하면, 즉 JavaScript 객체를 사용하여 어레이의 값 인덱스를 작성하면 O(N*M)에서 "아마도" 선형 시간으로 단축됩니다.source1 source2

function intersect(a, b) {
  var aa = {};
  a.forEach(function(v) { aa[v]=1; });
  return b.filter(function(v) { return v in aa; });
}

이것은 매우 간단한 솔루션(filter+indexOf보다 더 많은 코드)도 아니고, 매우 빠른 솔루션(아마도 cross_safe()보다 일정한 계수로 느림)도 아니지만, 꽤 좋은 밸런스인 것 같습니다.매우 심플하면서도 뛰어난 성능을 제공하며 사전 정렬된 입력이 필요하지 않습니다.

문자열 또는 숫자만 포함된 배열의 경우 다른 응답과 같이 정렬 작업을 수행할 수 있습니다.임의의 오브젝트 배열의 일반적인 경우, 나는 당신이 그것을 멀리하지 않을 수 없다고 생각한다.다음으로 파라미터로 제공되는 어레이의 수를 나타냅니다.arrayIntersection:

var arrayContains = Array.prototype.indexOf ?
    function(arr, val) {
        return arr.indexOf(val) > -1;
    } :
    function(arr, val) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === val) {
                return true;
            }
        }
        return false;
    };

function arrayIntersection() {
    var val, arrayCount, firstArray, i, j, intersection = [], missing;
    var arrays = Array.prototype.slice.call(arguments); // Convert arguments into a real array

    // Search for common values
    firstArray = arrays.pop();
    if (firstArray) {
        j = firstArray.length;
        arrayCount = arrays.length;
        while (j--) {
            val = firstArray[j];
            missing = false;

            // Check val is present in each remaining array 
            i = arrayCount;
            while (!missing && i--) {
                if ( !arrayContains(arrays[i], val) ) {
                    missing = true;
                }
            }
            if (!missing) {
                intersection.push(val);
            }
        }
    }
    return intersection;
}

arrayIntersection( [1, 2, 3, "a"], [1, "a", 2], ["a", 1] ); // Gives [1, "a"]; 

다양한 수의 어레이를 한 번에 처리할 수 있는 또 다른 인덱스 접근법:

// Calculate intersection of multiple array or object values.
function intersect (arrList) {
    var arrLength = Object.keys(arrList).length;
        // (Also accepts regular objects as input)
    var index = {};
    for (var i in arrList) {
        for (var j in arrList[i]) {
            var v = arrList[i][j];
            if (index[v] === undefined) index[v] = 0;
            index[v]++;
        };
    };
    var retv = [];
    for (var i in index) {
        if (index[i] == arrLength) retv.push(i);
    };
    return retv;
};

이 기능은 문자열로 평가할 수 있는 값에만 작동하며 다음과 같은 배열로 전달해야 합니다.

intersect ([arr1, arr2, arr3...]);

...단, 객체를 파라미터 또는 교차하는 요소 중 하나로 투과적으로 받아들입니다(항상 공통값의 배열을 반환합니다).예:

intersect ({foo: [1, 2, 3, 4], bar: {a: 2, j:4}}); // [2, 4]
intersect ([{x: "hello", y: "world"}, ["hello", "user"]]); // ["hello"]

편집: 어떻게 보면 약간 버그가 있는 것 같습니다.

즉, 다음과 같습니다.입력 어레이 자체에 반복을 포함할 수 없다고 생각하여 코드화했습니다(예: 그렇지 않음).

그러나 입력 배열에 반복이 포함되어 있으면 잘못된 결과가 발생합니다.예(아래 구현 사용):

intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]

다행히 두 번째 수준의 인덱스를 추가하는 것만으로 쉽게 수정할 수 있습니다.즉, 다음과 같습니다.

변경:

        if (index[v] === undefined) index[v] = 0;
        index[v]++;

기준:

        if (index[v] === undefined) index[v] = {};
        index[v][i] = true; // Mark as present in i input.

...그리고:

         if (index[i] == arrLength) retv.push(i);

기준:

         if (Object.keys(index[i]).length == arrLength) retv.push(i);

완전한 예:

// Calculate intersection of multiple array or object values.
function intersect (arrList) {
    var arrLength = Object.keys(arrList).length;
        // (Also accepts regular objects as input)
    var index = {};
    for (var i in arrList) {
        for (var j in arrList[i]) {
            var v = arrList[i][j];
            if (index[v] === undefined) index[v] = {};
            index[v][i] = true; // Mark as present in i input.
        };
    };
    var retv = [];
    for (var i in index) {
        if (Object.keys(index[i]).length == arrLength) retv.push(i);
    };
    return retv;
};

intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]); // [ '1' ]

데이터에 대한 몇 가지 제한이 있지만 선형 시간 에 작업을 수행할 수 있습니다.

의 정수: 값을 "보이는/보이지 않는" 부울에 매핑하는 배열을 사용합니다.

function intersectIntegers(array1,array2) { 
   var seen=[],
       result=[];
   for (var i = 0; i < array1.length; i++) {
     seen[array1[i]] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if ( seen[array2[i]])
        result.push(array2[i]);
   }
   return result;
}

오브젝트에도 같은 기술이 있습니다.더미 키를 가져와서 array1 내의 각 요소에 대해 "true"로 설정한 후 array2의 요소에서 이 키를 찾습니다.다 치우면 치워.

function intersectObjects(array1,array2) { 
   var result=[];
   var key="tmpKey_intersect"
   for (var i = 0; i < array1.length; i++) {
     array1[i][key] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if (array2[i][key])
        result.push(array2[i]);
   }
   for (var i = 0; i < array1.length; i++) {
     delete array1[i][key];
   }
   return result;
}

물론 이전에 키가 표시되지 않았는지 확인해야 합니다.그렇지 않으면 데이터가 파괴됩니다.

function intersection(A,B){
var result = new Array();
for (i=0; i<A.length; i++) {
    for (j=0; j<B.length; j++) {
        if (A[i] == B[j] && $.inArray(A[i],result) == -1) {
            result.push(A[i]);
        }
    }
}
return result;
}

심플화를 위해:

// Usage
const intersection = allLists
  .reduce(intersect, allValues)
  .reduce(removeDuplicates, []);


// Implementation
const intersect = (intersection, list) =>
  intersection.filter(item =>
    list.some(x => x === item));

const removeDuplicates = (uniques, item) =>
  uniques.includes(item) ? uniques : uniques.concat(item);


// Example Data
const somePeople = [bob, doug, jill];
const otherPeople = [sarah, bob, jill];
const morePeople = [jack, jill];

const allPeople = [...somePeople, ...otherPeople, ...morePeople];
const allGroups = [somePeople, otherPeople, morePeople];

// Example Usage
const intersection = allGroups
  .reduce(intersect, allPeople)
  .reduce(removeDuplicates, []);

intersection; // [jill]

이점:

  • 아주 간단한
  • 데이터 중심의
  • 임의의 개수의 리스트에 대해서 동작합니다.
  • 임의의 길이의 리스트에 대해 동작합니다.
  • 임의의 유형의 값에 대해 동작합니다.
  • 임의의 정렬 순서로 동작합니다.
  • 형상 유지(어레이의 첫 번째 표시 순서)
  • 가능한 한 빨리 퇴장하다
  • 메모리 세이프, 기능/어레이 프로토타입 조작 제외

결점:

  • 메모리 사용량 증가
  • CPU 사용률 증가
  • 감소에 대한 이해가 필요하다
  • 데이터 흐름에 대한 이해 필요

3D 엔진이나 커널 작업에는 사용하고 싶지 않지만 이벤트 기반 앱에서 실행하는 데 문제가 있다면 설계에 더 큰 문제가 있습니다.

나는 나에게 가장 잘 맞는 것을 위해 공헌할 것이다.

if (!Array.prototype.intersect){
Array.prototype.intersect = function (arr1) {

    var r = [], o = {}, l = this.length, i, v;
    for (i = 0; i < l; i++) {
        o[this[i]] = true;
    }
    l = arr1.length;
    for (i = 0; i < l; i++) {
        v = arr1[i];
        if (v in o) {
            r.push(v);
        }
    }
    return r;
};
}

ES2015를 통한 기능적 접근법

기능적 접근법은 부작용이 없는 순수한 기능만을 사용하는 것을 고려해야 하며, 각 기능은 하나의 작업에만 관련이 있다.

이러한 제한은 관련된 함수의 구성 가능성과 재사용 가능성을 향상시킵니다.

// small, reusable auxiliary functions

const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const apply = f => x => f(x);


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run it

console.log( intersect(xs) (ys) );

★★★★★★★★★★★에 주의해 주세요.Set타이핑하다

중복 방지

에서 반복적으로 발생하는 항목Array "" " " " " " " " " " " " " " " " " 가 보존됩니다.Array는 복제 해제됩니다.이것은 바람직한 동작일 수도 있고 그렇지 않을 수도 있습니다.만 하면 됩니다.dedupe에 대해서: "Manager" "Manager:

// auxiliary functions

const apply = f => x => f(x);
const comp = f => g => x => f(g(x));
const afrom = apply(Array.from);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// de-duplication

const dedupe = comp(afrom) (createSet);


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// unique result

console.log( intersect(dedupe(xs)) (ys) );

을 구합니다.Arrays

Array 작곡하면 돼요.intersectfoldl편의 기능은 다음과 같습니다.

// auxiliary functions

const apply = f => x => f(x);
const uncurry = f => (x, y) => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// intersection of an arbitrarily number of Arrays

const intersectn = (head, ...tail) => foldl(intersect) (head) (tail);


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
const zs = [0,1,2,3,4,5,6];


// run

console.log( intersectn(xs, ys, zs) );

.reduce.filter이치노 delete의 범위 내에서.filter두 번째 어레이를 하나의 세트처럼 취급할 수 있습니다.

function intersection (a, b) {
  var seen = a.reduce(function (h, k) {
    h[k] = true;
    return h;
  }, {});

  return b.filter(function (k) {
    var exists = seen[k];
    delete seen[k];
    return exists;
  });
}

나는 이 접근방식이 꽤 설득하기 쉽다고 생각한다.일정한 시간에 동작합니다.

오브젝트의 특정 속성을 바탕으로 오브젝트 배열의 교차점까지 검출할 수 있는 인스펙션 기능을 작성했습니다.

예를 들어.

if arr1 = [{id: 10}, {id: 20}]
and arr2 =  [{id: 20}, {id: 25}]

라는 것을 기준으로 교차로를 요.id은 다음과

[{id: 20}]

이와 같이 동일한 기능(주: ES6 코드)은 다음과 같습니다.

const intersect = (arr1, arr2, accessors = [v => v, v => v]) => {
    const [fn1, fn2] = accessors;
    const set = new Set(arr2.map(v => fn2(v)));
    return arr1.filter(value => set.has(fn1(value)));
};

함수를 다음과 같이 호출할 수 있습니다.

intersect(arr1, arr2, [elem => elem.id, elem => elem.id])

주의: 이 함수는 첫 번째 배열을 프라이머리 배열로 간주하여 교차점을 찾습니다. 따라서 교차점 결과는 프라이머리 배열로 간주됩니다.

함수는 사전의 기능을 활용하여 N^2 문제를 회피합니다.각 어레이를 1회만 루프하고 3번째 이하의 짧은 루프를 사용하여 최종 결과를 반환합니다.숫자, 문자열 개체도 지원합니다.

function array_intersect(array1, array2) 
{
    var mergedElems = {},
        result = [];

    // Returns a unique reference string for the type and value of the element
    function generateStrKey(elem) {
        var typeOfElem = typeof elem;
        if (typeOfElem === 'object') {
            typeOfElem += Object.prototype.toString.call(elem);
        }
        return [typeOfElem, elem.toString(), JSON.stringify(elem)].join('__');
    }

    array1.forEach(function(elem) {
        var key = generateStrKey(elem);
        if (!(key in mergedElems)) {
            mergedElems[key] = {elem: elem, inArray2: false};
        }
    });

    array2.forEach(function(elem) {
        var key = generateStrKey(elem);
        if (key in mergedElems) {
            mergedElems[key].inArray2 = true;
        }
    });

    Object.values(mergedElems).forEach(function(elem) {
        if (elem.inArray2) {
            result.push(elem.elem);
        }
    });

    return result;
}

수정만으로 해결할 수 없는 특별한 경우가 있는 경우generateStrKey확실히 해결할 수 있을 거예요.이 함수의 요령은 유형 및 값에 따라 각각 다른 데이터를 고유하게 나타낸다는 것입니다.


이 변형에는 몇 가지 성능이 향상되었습니다.어레이가 비어 있는 경우에는 루프를 피합니다.또한 먼저 짧은 배열부터 시작하므로 두 번째 배열에서 첫 번째 배열의 모든 값을 찾으면 루프가 종료됩니다.

function array_intersect(array1, array2) 
{
    var mergedElems = {},
        result = [],
        firstArray, secondArray,
        firstN = 0, 
        secondN = 0;

    function generateStrKey(elem) {
        var typeOfElem = typeof elem;
        if (typeOfElem === 'object') {
            typeOfElem += Object.prototype.toString.call(elem);
        }
        return [typeOfElem, elem.toString(), JSON.stringify(elem)].join('__');
    }

    // Executes the loops only if both arrays have values
    if (array1.length && array2.length) 
    {
        // Begins with the shortest array to optimize the algorithm
        if (array1.length < array2.length) {
            firstArray = array1;
            secondArray = array2;
        } else {
            firstArray = array2;
            secondArray = array1;            
        }

        firstArray.forEach(function(elem) {
            var key = generateStrKey(elem);
            if (!(key in mergedElems)) {
                mergedElems[key] = {elem: elem, inArray2: false};
                // Increases the counter of unique values in the first array
                firstN++;
            }
        });

        secondArray.some(function(elem) {
            var key = generateStrKey(elem);
            if (key in mergedElems) {
                if (!mergedElems[key].inArray2) {
                    mergedElems[key].inArray2 = true;
                    // Increases the counter of matches
                    secondN++;
                    // If all elements of first array have coincidence, then exits the loop
                    return (secondN === firstN);
                }
            }
        });

        Object.values(mergedElems).forEach(function(elem) {
            if (elem.inArray2) {
                result.push(elem.elem);
            }
        });
    }

    return result;
}

underscore.js의 실장은 다음과 같습니다.

_.intersection = function(array) {
  if (array == null) return [];
  var result = [];
  var argsLength = arguments.length;
  for (var i = 0, length = array.length; i < length; i++) {
    var item = array[i];
    if (_.contains(result, item)) continue;
    for (var j = 1; j < argsLength; j++) {
      if (!_.contains(arguments[j], item)) break;
    }
    if (j === argsLength) result.push(item);
  }
  return result;
};

출처 : http://underscorejs.org/docs/underscore.html#section-62

하나의 어레이를 사용하여 개체를 만들고 두 번째 어레이를 루프하여 값이 키로 존재하는지 확인합니다.

function intersection(arr1, arr2) {
  var myObj = {};
  var myArr = [];
  for (var i = 0, len = arr1.length; i < len; i += 1) {
    if(myObj[arr1[i]]) {
      myObj[arr1[i]] += 1; 
    } else {
      myObj[arr1[i]] = 1;
    }
  }
  for (var j = 0, len = arr2.length; j < len; j += 1) {
    if(myObj[arr2[j]] && myArr.indexOf(arr2[j]) === -1) {
      myArr.push(arr2[j]);
    }
  }
  return myArr;
}

내부에서 오브젝트를 사용하는 것은 계산에 도움이 되고 퍼포먼스도 향상될 수 있다고 생각합니다.

// 접근법은 각 요소의 카운트를 유지하며 음의 요소에도 작용합니다.

function intersect(a,b){
    
    const A = {};
    a.forEach((v)=>{A[v] ? ++A[v] : A[v] = 1});
    const B = {};
    b.forEach((v)=>{B[v] ? ++B[v] : B[v] = 1});
    const C = {};
    Object.entries(A).map((x)=>C[x[0]] = Math.min(x[1],B[x[0]]))
    return Object.entries(C).map((x)=>Array(x[1]).fill(Number(x[0]))).flat();
}
const x = [1,1,-1,-1,0,0,2,2];
const y = [2,0,1,1,1,1,0,-1,-1,-1];
const result = intersect(x,y);
console.log(result);  // (7) [0, 0, 1, 1, 2, -1, -1]

저는 맵 even 오브젝트를 사용할 수 있는 맵을 사용하고 있습니다.

//find intersection of 2 arrs
const intersections = (arr1,arr2) => {
  let arrf = arr1.concat(arr2)
  let map = new Map();
  let union = [];
  for(let i=0; i<arrf.length; i++){
    if(map.get(arrf[i])){
      map.set(arrf[i],false);
    }else{
      map.set(arrf[i],true);
    }
  }
 map.forEach((v,k)=>{if(!v){union.push(k);}})
 return union;
}

가장 단순하고 빠른 O(n) 및 최단 경로:

function intersection (a, b) {
    const setA = new Set(a);
    return b.filter(value => setA.has(value));
}

console.log(intersection([1,2,3], [2,3,4,5]))

@nbarbosa는 거의 같은 답을 가지고 있지만, 그는 두 어레이를 모두 에 던졌습니다.Set그리고 나서array추가 캐스팅은 필요 없습니다.

저는 타룰렌의 답변을 몇 개의 어레이로 작업하도록 확장했습니다.또, 정수 이외의 값에서도 동작합니다.

function intersect() { 
    const last = arguments.length - 1;
    var seen={};
    var result=[];
    for (var i = 0; i < last; i++)   {
        for (var j = 0; j < arguments[i].length; j++)  {
            if (seen[arguments[i][j]])  {
                seen[arguments[i][j]] += 1;
            }
            else if (!i)    {
                seen[arguments[i][j]] = 1;
            }
        }
    }
    for (var i = 0; i < arguments[last].length; i++) {
        if ( seen[arguments[last][i]] === last)
            result.push(arguments[last][i]);
        }
    return result;
}

어레이가 정렬되어 있는 경우 O(n)에서 실행됩니다.n은 min(a.length, b.length)입니다.

function intersect_1d( a, b ){
    var out=[], ai=0, bi=0, acurr, bcurr, last=Number.MIN_SAFE_INTEGER;
    while( ( acurr=a[ai] )!==undefined && ( bcurr=b[bi] )!==undefined ){
        if( acurr < bcurr){
            if( last===acurr ){
                out.push( acurr );
            }
            last=acurr;
            ai++;
        }
        else if( acurr > bcurr){
            if( last===bcurr ){
                out.push( bcurr );
            }
            last=bcurr;
            bi++;
        }
        else {
            out.push( acurr );
            last=acurr;
            ai++;
            bi++;
        }
    }
    return out;
}

var arrays = [
    [1, 2, 3],
    [2, 3, 4, 5]
]
function commonValue (...arr) {
    let res = arr[0].filter(function (x) {
        return arr.every((y) => y.includes(x))
    })
    return res;
}
commonValue(...arrays);

언급URL : https://stackoverflow.com/questions/1885557/simplest-code-for-array-intersection-in-javascript

반응형