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]
break
zu Simple js loops
erhöht die ops / s ~ 10M
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]
break
zu Simple js loops
erhöht die ops / s ~ 10M
Antworten:
Verwenden Sie eine Kombination aus Array.prototype.filter
und Array.prototype.indexOf
:
array1.filter(value => -1 !== array2.indexOf(value))
Oder wie vrugtehagel in den Kommentaren vorgeschlagen hat, können Sie den neueren Array.prototype.includes
für noch einfacheren Code verwenden:
array1.filter(value => array2.includes(value))
Für ältere Browser:
array1.filter(function(n) {
return array2.indexOf(n) !== -1;
});
intersection([1,2,1,1,3], [1])
kehrt zurück [1, 1, 1]
. Sollte es nicht einfach zurückkehren [1]
?
array2.indexOf(n) != -1
kann man auch array2.includes(n)
für noch einfacheren Code schreiben .
Destruktiv scheint am einfachsten zu sein, besonders wenn wir davon ausgehen können, 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 verfolgen 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;
}
intersect_safe
: length
ist eine Eigenschaft in Arrays, keine Methode. Es gibt eine nicht freigegebene Variable i
in result.push(a[i]);
. Schließlich funktioniert dies im allgemeinen Fall einfach nicht: Zwei Objekte, bei denen laut >
Operator keines größer als das andere ist, sind nicht unbedingt gleich. intersect_safe( [ {} ], [ {} ] )
Beispielsweise wird (sobald die zuvor genannten Fehler behoben sind) ein Array mit einem Element angegeben, was eindeutig falsch ist.
.slice(0)
einen Klon des Arrays erstellen intersect_safe
, anstatt Indizes zu verfolgen.
Wenn Ihre Umgebung ECMAScript 6 Set unterstützt , gibt es eine einfache und vermeintlich effiziente Möglichkeit (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 die zusätzliche Kreuzung zu erstellen Set
):
function intersect(a, b) {
return [...new Set(a)].filter(x => new Set(b).has(x));
}
Vermeiden Sie eine neue Set
aus b
jeder Zeit:
function intersect(a, b) {
var setB = new Set(b);
return [...new Set(a)].filter(x => setB.has(x));
}
Beachten Sie, dass Sie bei Verwendung von Sets nur unterschiedliche Werte erhalten, die daher zu new Set[1,2,3,3].size
ausgewertet werden 3
.
[...setA]
Syntax? Eine spezielle Art von Javascript-Operation?
x => new Set(b).has(x)
wiederum Pfeil Funktion b
in eine Reihe jedes Mal ausgeführt wird ? Sie sollten diesen Satz wahrscheinlich in einer Variablen speichern.
Verwenden von Underscore.js oder lodash.js
_.intersection( [0,345,324] , [1,0,324] ) // gives [0,324]
Mein Beitrag in ES6-Begriffen. Im Allgemeinen wird der Schnittpunkt eines Arrays mit einer unbestimmten Anzahl von Arrays gefunden, die als Argumente bereitgestellt werden.
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>");
[[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8],[4,5,6,7],[4,6]]
und gilt dann .reduce()
. Die erste [0,1,2,3,4,5,6,7,8,9].filter( e => [0,2,4,6,8].includes(e)
Operation wird ausgeführt und das Ergebnis wird das neue p
und c
wird [4,5,6,7]
in der nächsten Runde und setzt sich fort, bis keine mehr c
übrig ist.
prototype
unnötig.
// 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 die oben genannte prägnante Lösung, die andere Implementierungen bei großen Eingaben übertrifft. Wenn die Leistung bei kleinen Eingaben wichtig ist, überprüfen Sie die folgenden Alternativen.
Alternativen und Leistungsvergleich:
Weitere Implementierungen finden Sie im folgenden Snippet. Unter https://jsperf.com/array-intersection-comparison finden Sie Leistungsvergleiche.
Ergebnisse in Firefox 53:
Ops / Sek. Auf 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 / Sek. Auf 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
intersect([1,2,2,3], [2,3,4,5])
kehrt zurück [2, 2, 3]
.
a.filter(b.includes)
. Es sollte erheblich schneller laufen (genau wie Ihr Funktions-Upgrade).
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;
}
Object.prototype
.
d[b[i]] = true;
statt d[b[j]] = true;
( i
nicht j
) sein. Für die Bearbeitung sind jedoch 6 Zeichen erforderlich.
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 ist nur für Zahlen und normale Zeichenfolgen vorgesehen. Der Schnittpunkt von Arbitary Object Arrays funktioniert möglicherweise nicht.
Die Leistung der Implementierung von @ atk für sortierte Arrays von Grundelementen kann durch 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 mit jsPerf einen Benchmark erstellt: http://bit.ly/P9FrZK . Es ist ungefähr dreimal schneller, .pop zu verwenden.
a[aLast] > b[bLast]
mit a[aLast].localeCompare(b[bLast]) > 0
(und gleichen mit der weiter else if
unten) , dann wird dies auf Strings arbeiten.
.pop
O (1) und .shift()
O (n) ist
Verwenden von jQuery :
var a = [1,2,3];
var b = [2,3,4,5];
var c = $(b).not($(b).not(a));
alert(c);
c = $(b).filter(a);
, aber ich würde nicht empfehlen, sich für diese Art der Array-Manipulation auf jQuery zu verlassen, da in der Dokumentation nur erwähnt wird, dass es für Elemente funktioniert.
Bei Arrays, die nur Zeichenfolgen oder Zahlen enthalten, können Sie gemäß einigen der anderen Antworten etwas mit dem Sortieren tun. Für den allgemeinen Fall von Arrays beliebiger Objekte glaube ich nicht, dass Sie es auf lange Sicht vermeiden können. Im Folgenden erhalten Sie den Schnittpunkt einer beliebigen Anzahl von Arrays, die als Parameter für Folgendes bereitgestellt werden 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"];
firstArr
oder firstArray
und nicht alle Verweise aktualisieren. Fest.
Mit ES2015 und Sets ist es ziemlich kurz. 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(''));
Sie könnten eine Verwendung Set
als thisArg
von Array#filter
und nehmen Set#has
als Rückruf.
function intersection(a, b) {
return a.filter(Set.prototype.has, new Set(b));
}
console.log(intersection([1, 2, 3], [2, 3, 4, 5]));
Eine winzige Änderung an der kleinsten hier (der Filter / IndexOf-Lösung ), nämlich das Erstellen eines Index der Werte in einem der Arrays mithilfe eines JavaScript-Objekts, reduziert diese von O (N * M) auf "wahrscheinlich" lineare Zeit. Quelle1 Quelle2
function intersect(a, b) {
var aa = {};
a.forEach(function(v) { aa[v]=1; });
return b.filter(function(v) { return v in aa; });
}
Dies ist weder die einfachste Lösung (es ist mehr Code als filter + indexOf ) noch die schnellste (wahrscheinlich um einen konstanten Faktor langsamer als intersect_safe () ), scheint aber eine ziemlich gute Balance zu sein. Es ist sehr einfach, bietet aber eine gute Leistung und erfordert keine vorsortierten Eingaben.
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 wie folgt übergeben:
intersect ([arr1, arr2, arr3...]);
... aber es akzeptiert Objekte transparent als Parameter oder als eines der zu schneidenden Elemente (wobei immer ein Array gemeinsamer Werte zurückgegeben wird). 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, weil ich 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 (unter Verwendung der folgenden 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 Indizierung 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' ]
var v =
Hinzufügen der Zeile if (typeof v == 'function') continue;
wird das Hinzufügen von Funktionen zu den Ergebnissen übersprungen. Vielen Dank!
if (typeof v == 'function')
, dann können wir seine Stringifikation ( v.toString()
) als Schlüssel für den Index verwenden. Aber wir müssen etwas tun, um ihn intakt zu halten Am einfachsten ist es, einfach die ursprüngliche Funktion als Wert anstelle eines einfachen booleschen wahren Werts zuzuweisen. In diesem Fall sollte jedoch auch die neueste Deindexierung geändert werden, um diesen Zustand zu erkennen und den richtigen Wert (die Funktion) wiederherzustellen.
Sie können verwenden (für alle Browser außer IE):
const intersection = array1.filter(element => array2.includes(element));
oder für IE:
const intersection = array1.filter(element => array2.indexOf(element) !== -1);
Mit einigen Einschränkungen für Ihre Daten können Sie dies linear tun Zeit !
Für positive Ganzzahlen : Verwenden Sie ein Array, das die Werte einem Booleschen Wert "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 Objekte : Nehmen Sie einen Dummy-Schlüssel, setzen Sie ihn für jedes Element in Array1 auf "true" und suchen Sie diesen Schlüssel in Elementen von Array2. Räumen Sie auf, wenn Sie fertig sind.
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 vorher nicht angezeigt wurde, sonst zerstören Sie Ihre Daten ...
Ich werde mit dem 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;
};
}
"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]
'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))
Ein funktionaler Ansatz muss in Betracht ziehen, nur reine Funktionen ohne Nebenwirkungen zu verwenden, 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, der eine vorteilhafte Suchleistung bietet.
Offensichtlich Array
bleiben wiederholt vorkommende Elemente aus dem ersten erhalten, während das zweite nicht Array
dupliziert wird. Dies kann das gewünschte Verhalten sein oder auch nicht. Wenn Sie ein eindeutiges Ergebnis benötigen, wenden Sie einfach dedupe
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) );
Array
sWenn Sie den Schnittpunkt einer beliebigen Anzahl von Array
s berechnen möchten, komponieren Sie einfach intersect
mit foldl
. 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) );
(expr ? true : false)
ist redundant. Verwenden Sie nur, expr
wenn keine tatsächlichen Booleschen Werte benötigt werden, sondern nur "wahr" / "falsch".
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:
Nachteile:
Sie möchten dies nicht für 3D-Engine- oder Kernel-Arbeiten verwenden, aber wenn Sie Probleme haben, dies in einer ereignisbasierten App auszuführen, hat Ihr Design größere Probleme.
.reduce
um eine Karte zu erstellen und .filter
die Kreuzung zu finden. delete
Innerhalb von .filter
können wir das zweite Array so behandeln, als wäre es eine eindeutige Menge.
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 diesen Ansatz ziemlich einfach zu überlegen. Es arbeitet in konstanter Zeit.
Dies ist neben list1.filter (n => list2.includes (n)) wahrscheinlich die einfachste.
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"]
Wenn es mehrere Arrays schneiden muss:
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]
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]
Ich habe eine Schnittfunktion geschrieben, die sogar Schnittpunkte von Arrays 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 id
Eigenschaft, 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: Diese Funktion findet Schnittpunkte, wenn das erste Array das primäre Array ist und das Schnittpunktergebnis daher das des primären Arrays ist.
Denken Sie, dass dies mit der Zeit O (Array1 + Array2) schneller sein wird, vorausgesetzt, map.has () ist ~ O (1). Bitte korrigieren Sie mich, wenn Sie falsch liegen.
const intersection = (a1, a2) => {
let map = new Map();
let result = []
for (let i of a1) {
if (!map.has(i)) map.set(i, true);
}
for (let i of a2) {
if (map.has(i)) result.push(i)
}
return result;
}
Hier ist die Implementierung von 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;
};
Quelle: http://underscorejs.org/docs/underscore.html#section-62