it-swarm.com.de

Einfachster Code für die Überschneidung von Arrays in Javascript

Was ist der einfachste, bibliotheksfreie Code zum Implementieren von Array-Schnittpunkten in Javascript? Ich möchte schreiben

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

und bekomme

[2, 3]
440
Peter

Verwenden Sie eine Kombination aus Array.prototype.filter und Array.prototype.indexOf :

array1.filter(value => -1 !== array2.indexOf(value));
821
Anon.

Destruktiv scheint am einfachsten zu sein, insbesondere wenn angenommen werden kann, dass die Eingabe sortiert ist:

/* 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;
}

Zerstörungsfrei muss ein Haar komplizierter sein, da wir Indizes nachverfolgen müssen:

/* 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;
}
153
atk

Wenn Ihre Umgebung ECMAScript 6 Set unterstützt, eine einfache und vermeintlich effiziente Methode (siehe Spezifikationslink):

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

Kürzer, aber weniger lesbar (auch ohne Erstellung der zusätzlichen Schnittmenge Set):

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

Vermeiden Sie jedes Mal eine neue Set von b:

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

Beachten Sie, dass Sie bei der Verwendung von Sets nur unterschiedliche Werte erhalten. Daher wird new Set[1,2,3,3].size zu 3 ausgewertet.

45
nbarbosa

Underscore.js oder lodash.js verwenden

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

Mein Beitrag in ES6. Im Allgemeinen wird der Schnittpunkt eines Arrays mit einer unbestimmten Anzahl von Arrays als Argumente ermittelt.

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

12
Redu

Wie wäre es nur mit assoziativen Arrays?

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

bearbeiten:

// 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;
}
11
Steven Huwig

Verwenden von jQuery :

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

Die Leistung der @ atk-Implementierung für sortierte Primitiv-Arrays kann durch die Verwendung von .pop anstelle von .shift verbessert werden.

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

Ich habe einen Benchmark mit jsPerf erstellt: http://bit.ly/P9FrZK . Die Verwendung von .pop ist etwa dreimal schneller.

8
xn.

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

Ich empfehle eine prägnante Lösung, die andere Implementierungen bei großen Eingaben übertrifft. Wenn die Leistung bei kleinen Eingaben von Bedeutung ist, prüfen Sie die folgenden Alternativen.

Alternativen und Leistungsvergleich:

In dem folgenden Snippet finden Sie alternative Implementierungen, und https://jsperf.com/array-intersection-comparison für Leistungsvergleiche.

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

Ergebnisse in Firefox 53:

  • Ops/s bei großen Arrays (10.000 Elemente):

    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
    
  • Ops/s bei kleinen Arrays (100 Elemente):

    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
    
8
le_m

Bei Arrays, die nur Zeichenfolgen oder Zahlen enthalten, können Sie wie bei einigen anderen Antworten etwas sortieren. Für den allgemeinen Fall von Arrays beliebiger Objekte denke ich nicht, dass Sie es vermeiden können, den langen Weg zu tun. Im Folgenden erhalten Sie die Schnittmenge einer beliebigen Anzahl von Arrays, die als Parameter für arrayIntersection bereitgestellt werden:

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"]; 
7
Tim Down

Es ist ziemlich kurz mit ES2015 und Sets. Akzeptiert Array-ähnliche Werte wie einen String und entfernt Duplikate.

let intersection = function(a, b) {
  a = new Set(a), b = new Set(b);
  return [...a].filter(v => b.has(v));
};

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

console.log(intersection('ccaabbab', 'addb').join(''));

7
SeregPie
  1. Sortiere es
  2. Überprüfen Sie nacheinander den Index 0, und erstellen Sie daraus ein neues Array.

So etwas, aber nicht gut getestet.

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: Der Algorithmus, der nur für Zahlen und normale Zeichenfolgen vorgesehen ist, funktioniert möglicherweise nicht. 

7
YOU

Ein kleiner Tweak auf den kleinsten Wert (die filter/indexOf-Lösung ), dh das Erstellen eines Index der Werte in einem der Arrays mithilfe eines JavaScript-Objekts, wird ihn wahrscheinlich von O (N * M) auf "wahrscheinlich" reduzieren "lineare Zeit. source1source2

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

Dies ist nicht die einfachste Lösung (es ist mehr Code als filter + indexOf ), noch ist es die schnellste (wahrscheinlich um einen konstanten Faktor langsamer als intersect_safe () ), scheint aber ziemlich hübsch zu sein Gute Balance. Es ist auf der einfachen Seite sehr, bietet gute Leistung und erfordert keine vorsortierten Eingaben.

5
David

Ein weiterer indizierter Ansatz, der eine beliebige Anzahl von Arrays gleichzeitig verarbeiten kann:

// 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;
};

Es funktioniert nur für Werte, die als Zeichenfolgen ausgewertet werden können, und Sie sollten sie als Array übergeben:

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

... aber es akzeptiert Objekte transparent als Parameter oder als eines der zu schneidenden Elemente (gibt immer ein Array mit gemeinsamen Werten zurück). Beispiele:

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

EDIT: Ich habe gerade bemerkt, dass dies in gewisser Weise etwas fehlerhaft ist.

Das heißt: Ich habe es codiert und dachte, dass Eingabearrays selbst keine Wiederholungen enthalten können (wie im angegebenen Beispiel nicht).

Wenn Eingabearrays jedoch Wiederholungen enthalten, führt dies zu falschen Ergebnissen. Beispiel (mit untenstehender Implementierung):

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

Glücklicherweise lässt sich dies leicht beheben, indem einfach die Indexierung der zweiten Ebene hinzugefügt wird. Das ist:

Veränderung:

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

durch:

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

...und:

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

durch:

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

Vollständiges Beispiel:

// 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' ]
5
bitifet

Mit einigen Einschränkungen für Ihre Daten können Sie dies in linear time tun!

Für positive Ganzzahlen : Verwenden Sie ein Array, das die Werte einem Boolean "gesehen/nicht gesehen" zuordnet.

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

Es gibt eine ähnliche Technik für objects : Nehmen Sie einen Dummy-Schlüssel, setzen Sie ihn für jedes Element in array1 auf "true", und suchen Sie diesen Schlüssel in den Elementen von array2. Mach auf, wenn du fertig bist.

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

Natürlich müssen Sie sicher sein, dass der Schlüssel nicht zuvor angezeigt wurde. Andernfalls werden Sie Ihre Daten zerstören. 

4
tarulen
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;
}
4
Gabe

"indexOf" für IE 9.0, Chrome, Firefox, Oper, 

    function intersection(a,b){
     var rs = [], x = a.length;
     while (x--) b.indexOf(a[x])!=-1 && rs.Push(a[x]);
     return rs.sort();
    }

intersection([1,2,3], [2,3,4,5]);
//Result:  [2,3]

Dies ist wahrscheinlich das einfachste, Neben list1.filter (n => list2.includes (n))

var list1 = ['bread', 'ice cream', 'cereals', 'strawberry', 'chocolate']
var list2 = ['bread', 'cherry', 'ice cream', 'oats']

function check_common(list1, list2){
	
	list3 = []
	for (let i=0; i<list1.length; i++){
		
		for (let j=0; j<list2.length; j++){	
			if (list1[i] === list2[j]){
				list3.Push(list1[i]);				
			}		
		}
		
	}
	return list3
	
}

check_common(list1, list2) // ["bread", "ice cream"]

3
Chris Lwin

Sie können (für alle Browser außer IE) Folgendes verwenden:

const intersection = array1.filter(element => array2.includes(element));

oder für IE:

const intersection = array1.filter(element => array2.indexOf(element) !== -1);
3
jota3

Ich werde dazu beitragen, was für mich am besten funktioniert hat:

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;
};
}
3
Johan

.reduce zum Erstellen einer Karte und .filter zum Suchen der Kreuzung. delete im .filter erlaubt es uns, das zweite Array als eine eindeutige Menge zu behandeln.

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

Ich finde, dass diese Herangehensweise ziemlich einfach ist. Es arbeitet in konstanter Zeit.

2
Belden

'use strict'

// Example 1
function intersection(a1, a2) {
    return a1.filter(x => a2.indexOf(x) > -1)
}

// Example 2 (prototype function)
Array.prototype.intersection = function(arr) {
    return this.filter(x => arr.indexOf(x) > -1)
} 

const a1 = [1, 2, 3]
const a2 = [2, 3, 4, 5]

console.log(intersection(a1, a2))
console.log(a1.intersection(a2))

2
Vlad Bezden

Ein funktionaler Ansatz mit ES2015

Ein funktionaler Ansatz muss nur die Verwendung reiner Funktionen ohne Nebenwirkungen in Betracht ziehen, von denen jede nur einen einzelnen Job betrifft.

Diese Einschränkungen verbessern die Zusammensetzbarkeit und Wiederverwendbarkeit der beteiligten Funktionen.

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

Bitte beachten Sie, dass der native Set-Typ verwendet wird, was eine vorteilhafte Lookup-Leistung bietet.

Vermeiden Sie Duplikate

Offensichtlich werden wiederholt vorkommende Elemente aus der ersten Array beibehalten, während die zweite Array entdupliziert wird. Dies kann das gewünschte Verhalten sein oder nicht. Wenn Sie ein eindeutiges Ergebnis benötigen, wenden Sie einfach dedupe auf das erste Argument an:

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

Berechnen Sie den Schnittpunkt einer beliebigen Anzahl von Arrays

Wenn Sie die Schnittmenge einer beliebigen Anzahl von Arrays berechnen möchten, setzen Sie einfach intersect mit foldl zusammen. Hier ist eine Komfortfunktion:

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

2
user6445533

Der Einfachheit halber:

// 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]

Leistungen:

  • schmutz einfach
  • datenzentriert
  • funktioniert für eine beliebige Anzahl von Listen
  • arbeitet für beliebige Längen von Listen
  • funktioniert für beliebige Werte
  • arbeitet für beliebige Sortierreihenfolge
  • behält die Form (Reihenfolge des ersten Auftretens in einem beliebigen Array)
  • wenn möglich frühzeitig beendet
  • speichersicher, mit Manipulationen an Funktion/Array-Prototypen

Nachteile:

  • höhere Speicherauslastung
  • höhere CPU-Auslastung
  • erfordert ein Verständnis von reduzieren
  • erfordert ein Verständnis des Datenflusses

Sie möchten dies nicht für die 3D-Engine oder den Kernel verwenden, aber wenn Sie Probleme damit haben, dies in einer ereignisbasierten App auszuführen, hat Ihr Design größere Probleme.

2
Norguard
var listA = [1,2,3,4,5,6,7];
var listB = [2,4,6,8];

var result = listA.filter(itemA=> {
    return listB.some(itemB => itemB === itemA);
});
1
jcmordan

Anstatt indexOf zu verwenden, können Sie auch Array.prototype.includes verwenden.

function intersection(arr1, arr2) {
  return arr1.filter((ele => {
    return arr2.includes(ele);
  }));
}

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

1
AZ_

Hier ist underscore.js Implementierung:

_.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;
};

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

1
Dorian
function getIntersection(arr1, arr2){
    var result = [];
    arr1.forEach(function(elem){
        arr2.forEach(function(elem2){
            if(elem === elem2){
                result.Push(elem);
            }
        });
    });
    return result;
}

getIntersection([1,2,3], [2,3,4,5]); // [ 2, 3 ]
1
bekzat

Wenn Sie mehrere Arrays kreuzen müssen:

const intersect = (a, b, ...rest) => {
  if (rest.length === 0) return [...new Set(a)].filter(x => new Set(b).has(x));
  return intersect(a, intersect(b, ...rest));
};

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

1
Belfordz

Ich habe eine Intesection-Funktion geschrieben, die sogar Schnittmengen von Objekten basierend auf bestimmten Eigenschaften dieser Objekte erkennen kann.

Zum Beispiel,

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

und wir wollen eine Schnittmenge basierend auf der Eigenschaft id, dann sollte die Ausgabe sein:

[{id: 20}]

Daher lautet die Funktion für dasselbe (Hinweis: ES6-Code):

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

und Sie können die Funktion aufrufen als:

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

Beachten Sie auch, dass diese Funktion die Schnittmenge ermittelt, wenn das erste Array das primäre Array ist und das Ergebnis der Schnittmenge das des primären Arrays ist.

1
Mridul Meharia

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

1
user1046987

Sie müssen keine Zwischenvariable innerhalb der Funktion für das zweite Array angeben, wenn das zweite Array immer als set behandelt wird.

Die folgende Lösung gibt ein Array eindeutiger Werte zurück, die in beiden Arrays vorkommen:

const intersection = (a, b) => {
  b = new Set(b); // recycling variable
  return [...new Set(a)].filter(e => b.has(e));
};

console.log(intersection([1, 2, 3, 1, 1], [1, 2, 4])); // Array [ 1, 2 ]
0
Grant Miller

Sie könnten eine Set als thisArg von Array#filter verwenden und Set#has als Rückruf nehmen.

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

console.log(intersection([1, 2, 3], [2, 3, 4, 5]));
0
Nina Scholz

Hoffe das hilft bei allen Versionen.

function diffArray(arr1, arr2) {
  var newArr = [];

  var large = arr1.length>=arr2.length?arr1:arr2;
  var small = JSON.stringify(large) == JSON.stringify(arr1)?arr2:arr1;
  for(var i=0;i<large.length;i++){
    var copyExists = false; 
    for(var j =0;j<small.length;j++){
      if(large[i]==small[j]){
        copyExists= true;
        break;
      }
    }
    if(!copyExists)
      {
        newArr.Push(large[i]);
      }
  }

  for(var i=0;i<small.length;i++){
    var copyExists = false; 
    for(var j =0;j<large.length;j++){
      if(large[j]==small[i]){
        copyExists= true;
        break;
      }
    }
    if(!copyExists)
      {
        newArr.Push(small[i]);
      }
  }


  return newArr;
}
0
Shubham Pandey

ES6-Stil auf einfache Weise.

const intersection = (a, b) => {
  const s = new Set(b);
  return a.filter(x => s.has(x));
};

Beispiel:

intersection([1, 2, 3], [4, 3, 2]); // [2, 3]
0
Alex Petre

Erstellen Sie ein Objekt mit einem Array und durchlaufen Sie das zweite Array, um zu prüfen, ob der Wert als Schlüssel vorhanden ist.

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;
}
0
sridhar reddy

Wenn Ihre Arrays sortiert sind, sollte dies in O (n) laufen, wobei n min ist (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;
}
0
Dave Swanson

Hier ist eine sehr naive Implementierung, die ich verwende. Es ist zerstörungsfrei und stellt auch sicher, dass ganze Elemente nicht dupliziert werden.

Array.prototype.contains = function(elem) {
    return(this.indexOf(elem) > -1);
};

Array.prototype.intersect = function( array ) {
    // this is naive--could use some optimization
    var result = [];
    for ( var i = 0; i < this.length; i++ ) {
        if ( array.contains(this[i]) && !result.contains(this[i]) )
            result.Push( this[i] );
    }
    return result;
}
0
devios1

Wenn Sie die akzeptierte Antwort verwenden möchten, aber Unterstützung für Internet Explorer benötigen, müssen Sie die Abkürzung der Pfeilfunktion vermeiden. Hier ist der bearbeitete Einzeiler, der auch in IE funktionieren wird:

// accepted aswer: array1.filter(value => -1 !== array2.indexOf(value));
// IE-supported syntax:
array1.filter(function(value) { return -1 !== array2.indexOf(value) });
0
KjetilNordin

Mit dem folgenden Code werden auch die Duplikate entfernt:

       function intersect(x, y) {
            if (y.length > x.length) temp = y, y = x, x= temp;  
            return x.filter(function (e, i, c) {  
                  return c.indexOf(e) === i;
                 });
       }
0
Enayat Rajabi

schnittpunkt von N Arrays in Kaffeescript

getIntersection: (arrays) ->
    if not arrays.length
        return []
    a1 = arrays[0]
    for a2 in arrays.slice(1)
        a = (val for val in a1 when val in a2)
        a1 = a
    return a1.unique()
0
user1205224

Aufbauend auf Anons exzellenter Antwort liefert diese die Schnittmenge von zwei oder mehr Arrays.

function arrayIntersect(arrayOfArrays)
{        
    var arrayCopy = arrayOfArrays.slice(),
        baseArray = arrayCopy.pop();

    return baseArray.filter(function(item) {
        return arrayCopy.every(function(itemList) {
            return itemList.indexOf(item) !== -1;
        });
    });
}
0

Ich habe Tarulens Antwort erweitert, um mit einer beliebigen Anzahl von Arrays zu arbeiten. Es sollte auch mit nicht ganzzahligen Werten arbeiten.

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;
}
0
gabe appleton

funktion intersectionOfArrays (arr1, arr2) {return arr1.filter ((element) => arr2.indexOf (element)! == -1) .filter ((element, pos, self) => self.indexOf (element) == pos);}

0
Prakash Mandal