Wie berechnet man den Schnittpunkt mehrerer Arrays in JavaScript? Und was tut [equals: function] bedeuten?

Lesezeit: 8 Minuten

Ich bin mir dieser Frage bewusst, dem einfachsten Code für die Schnittmenge von Arrays, aber alle Lösungen gehen davon aus, dass die Anzahl der Arrays zwei ist, was in meinem Fall nicht sicher sein kann.

Ich habe Divs auf einer Seite mit Daten, die Arrays enthalten. Ich möchte die Werte finden, die allen Arrays gemeinsam sind. Ich weiß nicht, wie viele Divs/Arrays ich im Voraus haben werde. Was ist der beste Weg, um Werte zu berechnen, die allen Arrays gemeinsam sind?

var array1 = ["Lorem", "ipsum", "dolor"];
var array2 = ["Lorem", "ipsum", "quick", "brown", "foo"];
var array3 = ["Jumps", "Over", "Lazy", "Lorem"];
var array4 = [1337, 420, 666, "Lorem"];
//Result should be ["Lorem"];

Ich habe an anderer Stelle eine andere Lösung mit Underscore.js gefunden.

var arrayOfArrays = [[4234, 2323, 43], [1323, 43, 1313], [23, 34, 43]];
_.intersection.apply(_, arrayOfArrays)
//Result is [43]

Ich habe dies mit einfachen Dummy-Daten an meinem Ende getestet und es scheint zu funktionieren. Aber aus irgendeinem Grund enthalten einige der von mir erstellten Arrays, die einfache Zeichenfolgen enthalten, auch automatisch einen zusätzlichen Wert, “equals: function”:

["Dummy1", "Dummy2", "Dummy3", equals: function]

Und immer wenn ich die Underscore.js-Schnittmethode für ein Array von Arrays verwende, bekomme ich immer [equals: function] in Entwicklungstools und nicht – wenn “Dummy3” allen Arrays gemeinsam ist – [“Dummy3”].

Also, TL; DR, gibt es eine andere Lösung für die Array-Schnittmenge, die für meinen Fall geeignet wäre? Und kann jemand erklären, was [equals: function] bedeutet hier? Wenn ich das Element in den Entwicklungstools erweitere, erzeugt es ein leeres Array und eine Liste von Methoden, die für Arrays verfügbar sind (Pop, Push, Shift usw.), aber diese Methoden werden alle ausgeblendet, während equals: function hervorgehoben wird.

  • Das Beispiel Underscore.js scheint etwas irreführend zu sein? Das letzte Array enthält nicht 43.

    – Arg0n

    19. Mai 16 um 10:22 Uhr

  • kk Ich werde das korrigieren :s

    Benutzer5102448

    19. Mai 16 um 10:23 Uhr

  • Du hast ein , fehlt am Ende array2. Ich habe es gerade mit versucht _.intersection(array1, array2, array3, array4) in der lodash.com-Konsole und es funktioniert zurück "Lorem"

    – Alberto Zaccagni

    19. Mai 16 um 10:23 Uhr

  • Ich weiß nicht im Voraus, wie viele Divs mit Daten ich haben werde. Ich öffne ein Fenster und divs erscheinen. Also kann ich nicht einfach _.intersection(array1… array4) machen. Ich könnte sie jedoch durchlaufen und in ein einzelnes Array von Arrays schieben, wenn das Fenster geladen wird, aber das verursacht das Problem, mit dem ich in der zweiten Hälfte erkläre [equals: function].

    Benutzer5102448

    19. Mai ’16 um 10:25 Uhr

Du könntest einfach verwenden Array#reduce mit Array#filter und Array#includes.

var array1 = ["Lorem", "ipsum", "dolor"],
    array2 = ["Lorem", "ipsum", "quick", "brown", "foo"],
    array3 = ["Jumps", "Over", "Lazy", "Lorem"],
    array4 = [1337, 420, 666, "Lorem"],
    data = [array1, array2, array3, array4],
    result = data.reduce((a, b) => a.filter(c => b.includes(c)));

console.log(result);

  • Was ist die mathematische Komplexität dieser Funktion? Sieht aus wie mindestens O(n²).

    – herabgesetzt

    8. März 19 um 3:36 Uhr

  • @ReactingToAngularVues, ​​es ist nicht quadratisch, da das Teilergebnis für jede Schleife kürzer werden kann.

    – Nina Scholz

    5. April 19 um 11:13 Uhr


  • Ich denke O(n * log n) ist richtig. Ich denke, eine Sache, die diese Lösung noch weiter optimieren würde, ist, zuerst das kürzeste Array zu finden und es auf den ersten Index des Datenarrays zu verschieben. In der Reduce-Funktion verwenden wir das erste Element in data als Ausgangspunkt und prüfen dann jedes Element in diesem Array. Wenn dieses anfängliche Array das kürzestmögliche ist, werden zusätzliche Iterationen entfernt. Stellen Sie sich zum Beispiel vor, dass unser Datenarray so aussieht: [[1, 2, 3, …. , 10000], [1]]Das Vertauschen der Reihenfolge dieser beiden Elemente würde einen großen Unterschied machen. Tolle Lösung, @NinaScholz !

    – Nathan

    20. Mai 21 um 16:40 Uhr

  • Es ist Ω(mn) für insgesamt n Elemente nach der ersten Liste und m letzte Elemente, was die gleiche Art von Leistungsfalle ist wie typische versehentlich quadratische Dinge. Leicht verbessert mit a Set.

    – Ry-

    10. November 21 um 5:54 Uhr

  • @ Nathan: Es ist definitiv nicht O (n log n).

    – Ry-

    10. November 21 um 5:54 Uhr

Wie berechnet man den Schnittpunkt mehrerer Arrays in JavaScript Und
Arg0n

Dazu habe ich eine Hilfsfunktion geschrieben:

function intersection() {
  var result = [];
  var lists;

  if(arguments.length === 1) {
    lists = arguments[0];
  } else {
    lists = arguments;
  }

  for(var i = 0; i < lists.length; i++) {
    var currentList = lists[i];
    for(var y = 0; y < currentList.length; y++) {
        var currentValue = currentList[y];
      if(result.indexOf(currentValue) === -1) {
        var existsInAll = true;
        for(var x = 0; x < lists.length; x++) {
          if(lists[x].indexOf(currentValue) === -1) {
            existsInAll = false;
            break;
          }
        }
        if(existsInAll) {
          result.push(currentValue);
        }
      }
    }
  }
  return result;
}

Verwenden Sie es wie folgt:

intersection(array1, array2, array3, array4); //["Lorem"]

Oder so:

intersection([array1, array2, array3, array4]); //["Lorem"]

Vollständiger Code Hier

AKTUALISIERUNG 1

Eine etwas kleinere Implementierung Hier verwenden filter

  • Danke dafür. Ich kann ihm folgen und es funktioniert mit Dummy-Daten, buuuut … Ich habe keine separaten Arrays, die in Variablen wie Array1 und Array2 und Array3 gespeichert sind, weil ich im Voraus nicht weiß, wie viele Divs auf der Seite sind. Im Moment muss ich sie durchschleifen und in ein anderes Container-Array schieben. Ich konnte also nur Schnittpunkte (arrayContainingArrays) ausführen, die mit Ihrem Code nicht funktionieren würden. Das heißt, dies ist eine gute Lösung in Vanille-JavaScript, die jemand anderes verwenden könnte.

    Benutzer5102448

    19. Mai ’16 um 10:48 Uhr

  • :O Okay! Gebt mir 5 Minuten, dann probiere ich das aus

    Benutzer5102448

    19. Mai 16 um 10:54 Uhr

  • Dies funktioniert perfekt für Dummy-Arrays, aber nicht für die spezifischen Arrays, die ich möchte. Was bedeutet, dass mir an meiner Seite noch etwas fehlt. Aber diese Antwort ist eine gute Lösung, die meine Frage vollständig beantwortet und für andere nützlich sein wird. So gewinnen Sie heute das Internet.

    Benutzer5102448

    19. Mai 16 um 11:09 Uhr

  • mit dem Datensatz: var array1 = [786, 796] var array2 = [100]; var array3 = [1]; var array4 = [2,3,4,1]; Die Ausgabe ist ein leeres Array, aber es sollten gemeinsame Werte sein. Bitte korrigieren Sie mich diesbezüglich. Danke schön.

    – NN796

    13. April 21 um 20:06 Uhr

  • @NN796 Sollte leer sein. In allen Arrays ist kein Wert vorhanden.

    – Arg0n

    15. April 21 um 5:25 Uhr

Wie berechnet man den Schnittpunkt mehrerer Arrays in JavaScript Und
1983

Dies kann ziemlich kurz und bündig erfolgen, wenn Sie Rekursion und die neue ES2015-Syntax verwenden möchten:

const array1 = ["Lorem", "ipsum", "dolor"];
const array2 = ["Lorem", "ipsum", "quick", "brown", "foo"];
const array3 = ["Jumps", "Over", "Lazy", "Lorem"];
const array4 = [1337, 420, 666, "Lorem"];

const arrayOfArrays = [[4234, 2323, 43], [1323, 43, 1313], [23, 34, 43]];

// Filter xs where, for a given x, there exists some y in ys where y === x.
const intersect2 = (xs,ys) => xs.filter(x => ys.some(y => y === x));

// When there is only one array left, return it (the termination condition
// of the recursion). Otherwise first find the intersection of the first
// two arrays (intersect2), then repeat the whole process for that result
// combined with the remaining arrays (intersect). Thus the number of arrays
// passed as arguments to intersect is reduced by one each time, until
// there is only one array remaining.
const intersect = (xs,ys,...rest) => ys === undefined ? xs : intersect(intersect2(xs,ys),...rest);

console.log(intersect(array1, array2, array3, array4));
console.log(intersect(...arrayOfArrays));

// Alternatively, in old money,

var intersect2ES5 = function (xs, ys) {
    return xs.filter(function (x) {
        return ys.some(function (y) {
            return y === x;
        });
    });
};
    
// Changed slightly from above, to take a single array of arrays,
// which matches the underscore.js approach in the Q., and is better anyhow.
var intersectES5 = function (zss) {
    var xs = zss[0];
    var ys = zss[1];
    var rest = zss.slice(2);
    if (ys === undefined) {
        return xs;
    }
    return intersectES5([intersect2ES5(xs, ys)].concat(rest));
};

console.log(intersectES5([array1, array2, array3, array4]));
console.log(intersectES5(arrayOfArrays));

  • Hm. Nie zuvor auf const oder rest gestoßen. Ich sollte mich besser über ECMAScript 6 informieren, bevor mein Arbeitgeber mich durch einen Roboter ersetzt 😮

    Benutzer5102448

    19. Mai ’16 um 16:34 Uhr

Mit einer Kombination aus Ideen mehrerer Mitwirkender und der neuesten ES6-Güte kam ich zu

const array1 = ["Lorem", "ipsum", "dolor"];
const array2 = ["Lorem", "ipsum", "quick", "brown", "foo"];
const array3 = ["Jumps", "Over", "Lazy", "Lorem"];
const array4 = [1337, 420, 666, "Lorem"];

Array.prototype.intersect = function intersect(a, ...b) {
    const c = function (a, b) {
        b = new Set(b);
        return a.filter((a) => b.has(a));
    };
    return undefined === a ? this : intersect.call(c(this, a), ...b);
};

console.log(array1.intersect(array2, array3, array4));
// ["Lorem"]

Für alle, die das in Zukunft verwirrt,

_.intersection.apply(_, arrayOfArrays)

Ist in der Tat der eleganteste Weg, dies zu tun. Aber:

var arrayOfArrays = [[43, 34343, 23232], [43, 314159, 343], [43, 243]];
arrayOfArrays = _.intersection.apply(_, arrayOfArrays);

Wird nicht funktionieren! Muss tun

var differentVariableName = _.intersection.apply(_,arrayOfArrays);

Wie berechnet man den Schnittpunkt mehrerer Arrays in JavaScript Und
Ygalbel

Ihr Code mit _lodash funktioniert einwandfrei.

Wie Sie sagen können Dies Geige:

dieser Code:

var arrayOfArrays = [[4234, 2323, 43], [1323, 43, 1313], [23, 34, 43]];
var a = _.intersection.apply(_, arrayOfArrays);
console.log(a);
console.log(a.length);

Wird ausgegeben:

[42]
1

Vielleicht sehen Sie

gleich: Funktion

weil Sie eine Art Debugger verwenden.

Versuchen Sie, das Array einfach mit zu drucken console.logerhalten Sie nur 42.

Kleine rekursive Teile-und-Herrsche-Lösung, die nicht auf es6 oder einer Bibliothek angewiesen ist.

Es akzeptiert ein Array von Arrays, wodurch der Code kürzer wird und Sie Argumente mithilfe von map übergeben können.

function intersection(a) {
    if (a.length > 2)
        return intersection([intersection(a.slice(0, a.length / 2)), intersection(a.slice(a.length / 2))]);

    if (a.length == 1)
        return a[0];

    return a[0].filter(function(item) {
        return a[1].indexOf(item) !== -1;
    });
}

var list1 = [ 'a', 'b', 'c' ];
var list2 = [ 'd', 'b', 'e' ];
var list3 = [ 'f', 'b', 'e' ];
console.log(intersection([list1, list2, list3]));

.

822340cookie-checkWie berechnet man den Schnittpunkt mehrerer Arrays in JavaScript? Und was tut [equals: function] bedeuten?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy