Warum funktioniert die Gleichheitsprüfung nicht mit Arrays? [duplicate]

Lesezeit: 9 Minuten

Warum funktioniert die Gleichheitsprufung nicht mit Arrays duplicate
Jacksonkr

Ich begann mit:

"1:2".split(':') == ["1","2"]; 
// false

Dann probiert:

[1,2] == [1,2];
// false

und ultimativ:

[] == []; 
// false

Das habe ich inzwischen gefunden:

"1:2".split(':').toString() == [1,2].toString();
// true

Also habe ich mein anfängliches Problem (irgendwie) gelöst, aber warum können Arrays nicht miteinander übereinstimmen?

  • Weder ==noch === elementweise vergleichen. Beide prüfen, ob beide Arrays ein und dasselbe sind.

    – das vierte Auge

    13. Juni 2015 um 15:57 Uhr

  • Dies liegt daran, dass Arrays in JavaScript Objekte sind. Vielleicht möchten Sie einen Blick auf diese stackoverflow.com/questions/22395357/…

    – ankur

    13. Juni 2015 um 15:58 Uhr


  • mögliches Duplikat von Why is not [1,2,3] gleich selbst in Javascript?

    – Bergi

    4. Mai 2018 um 16:22 Uhr

  • Beachten Sie, wenn Sie nur nach einem leeren Array suchen möchten, können Sie überprüfen, ob array.length === 0

    – nCardot

    6. September 2021 um 18:44 Uhr

1647262509 417 Warum funktioniert die Gleichheitsprufung nicht mit Arrays duplicate
uraimo

Javascript-Arrays sind Objekte und Sie können nicht einfach den Gleichheitsoperator verwenden == zu verstehen, ob die Inhalt dieser Objekte ist gleich. Der Gleichheitsoperator testet nur, ob zwei Objekte tatsächlich genau dieselbe Instanz sind (z myObjVariable==myObjVariablefunktioniert für null und undefined zu).

Wenn Sie überprüfen müssen, ob zwei Arrays gleich sind, würde ich empfehlen, einfach beide Arrays zu durchlaufen und zu überprüfen, ob alle Elemente denselben Wert haben (und dass die beiden Arrays dieselbe Länge haben).

In Bezug auf die Gleichheit benutzerdefinierter Objekte würde ich stattdessen eine spezifische erstellen equals Funktion und ich würde es dem Prototyp Ihrer Klasse hinzufügen.

Wenn man bedenkt, dass Sie am Ende beide Arrays in a konvertiert haben String und getestete Gleichheit der resultierenden Zeichenfolgen, könnten Sie eines Tages in Betracht ziehen, eine ähnliche, aber allgemeinere Technik zu verwenden, die Sie an mehr als ein paar Stellen beschrieben finden:

JSON.stringify(OBJ1) === JSON.stringify(OBJ2) 

Brunnen, nicht.

Dies könnte zwar funktionieren, wenn die Reihenfolge der Eigenschaften für diese Objektinstanzen immer gleich ist, aber dies lässt die Tür für extrem böse Fehler offen, die möglicherweise schwer aufzuspüren sind. Bevorzugen Sie immer einen expliziteren Ansatz und schreiben Sie einfach eine saubere und lesbare Funktion, die alle erforderlichen Felder auf Gleichheit prüft.

  • Interessanter Hinweis, myObjVariable == myObjectVariable ist in allen Instanzen von JS wahr, außer wo myObjVariable = NaN… 🙂

    – War10ck

    3. Mai 2018 um 20:21 Uhr

  • Es gibt viele interessante Notizen über NaN, eines der berühmtesten Wesen NaN.constructor === Number.

    – Dmitri

    3. Mai 2018 um 20:22 Uhr

Warum funktioniert die Gleichheitsprufung nicht mit Arrays duplicate
jfriend00

Die == -Operator für Objekte in Javascript überprüft nur, ob die Objekte dieselbe tatsächliche Objektreferenz sind, nicht, ob es sich um zwei separate Objekte handelt, die denselben Inhalt enthalten. Es gibt keinen eingebauten Operator, um zu prüfen, ob sie denselben Inhalt enthalten. Sie müssten eine Funktion schreiben, um diese Art von Vergleich selbst durchzuführen.

Ihre Zeichenfolgenkonvertierung ist eine Möglichkeit, zwei Arrays zu vergleichen, solange die Array-Elemente nur primitive Werte enthalten (keine anderen Objekte). Wenn die Array-Elemente andere Elemente enthalten könnten, müssten Sie sicherstellen, dass diese Objekte selbst auch in repräsentative Zeichenfolgen konvertiert werden.

Und das Konvertieren in eine Zeichenfolge würde nicht zwischen einem Array-Element unterscheiden, das enthält "4" gegen eine, die enthält 4 da konvertieren beide zu "4" in der Stringdarstellung.

1647262510 464 Warum funktioniert die Gleichheitsprufung nicht mit Arrays duplicate
Volkskunde

Gleichheit für Objekte wird Ihnen sagen, ob die beiden Objekte das sind gleiche.

var a = [];
var b = a;
a === b;    // True, a and b refer to the same object
[] === [];  // False, two separate objects

Sie müssen die Arrays durchlaufen, um zu sehen, ob sie dieselben Elemente enthalten.

Siehe: Wie überprüfe ich mit JavaScript, ob zwei Arrays gleich sind?

Jeweils in Javascript [] ist eine Instanz von window.Array Klasse. Sie versuchen also im Grunde, zwei verschiedene Objekte zu vergleichen. Da Arrays keine haben können. und jede Art von Elementen, einschließlich Objekten und benutzerdefinierten Objekten, und diese verschachtelten Arrays können wiederum zahlreiche Eigenschaften und Arrays usw. haben.

Wenn es um Vergleiche geht, wird es zweideutig, Sie werden nie sicher sein, was Sie mit diesen Objekten und verschachtelten Eigenschaften machen wollen. Was Sie also durch Vergleichen erreichen möchten, kann auf so viele andere Arten erreicht werden. Sie müssen nur den richtigen Weg für Ihren Fall finden.

1647262511 40 Warum funktioniert die Gleichheitsprufung nicht mit Arrays duplicate
Klickköder

Eine Möglichkeit ist, Ihre eigenen zu machen Array Prüffunktion:

Wie vergleicht man Arrays in JavaScript?!

Eine andere Möglichkeit ist die Konvertierung Array zu einem String mit .join(), und vergleichen Sie die Zeichenfolgen. Konvertieren Sie sie dann wieder in Arrays mit .split().

Meine Vermutung ist, dass sie bei der Entwicklung von Javascript dachten, dass der elementweise Vergleich eine selten verwendete Funktion sei, sodass er nie in die Sprache aufgenommen wurde.

Diese Funktion ist in populären Sprachen ziemlich selten; Java unterstützt es nicht, C# unterstützt es nicht, C++-STL-Typen unterstützen es nicht.

Der elementweise Vergleich ist im Vergleich zum Referenzvergleich ziemlich teuer und kompliziert.

In einer perfekten Welt kann alles durch Referenz verglichen werden, sodass alle zwei Objekte mit demselben Zustand dieselbe Referenz haben würden, was es uns ermöglicht, wirklich billig auf Gleichheit zu prüfen, indem wir einfach ihre internen virtuellen Adressen mit einem einfachen Zahlenvergleich vergleichen.

Leider leben wir nicht in einer perfekten Welt, und das Obige ist nur für Strings mit einem String-Pool möglich, zusammen mit einigen anderen relativ speicherintensiven Caching-Optionen.

Einige Sprachen wie Prolog und Haskell erlauben einen Vergleich nach Wert; z.B

myProgram :- 
    Object1 = [1, "something", true, [1,[[], []], true,[false]]],
    Object2 = [1, "something", false, [1,[[], []], true,[false]]],
    Object3 = [1, "something", true, [1,[[], []], true,[false]]],
    Object4 = [1, "something", false, [1,[[], []], true,[false]]],
    (Object1 = Object2 
        -> write("first test passed.")    
        ; write("first test failed\n")),
    (Object1 = Object3 
        -> write("second test passed!\n")
        ; write("second test failed!\n")),
    (Object2 = Object4
        -> write("third test passed!\n")
        ; write("third test failed!")).

Sie können Ihren eigenen Tiefenkomparator in jeder Sprache implementieren, indem Sie eine Zuordnung vom Konstruktor zu einem Komparator für diesen Konstruktor verwenden. Da JavaScript keine Zuordnungen von irgendetwas anderem als Zeichenfolgen zu Objekten hat und JavaScript-Clients keinen Zugriff auf die internen eindeutigen Bezeichner von Objekten haben, müssen wir eine Tabelle mit Konstruktor- und Komparatorpaaren verwenden, so etwas wie unten.

class MyList {
    constructor(a, b) {
        this.head_ = a;
        this.tail_ = b;
    }
    getHead() {
        return this.head_;
    }
    getTail() {
        return this.tail_;
    }
    setHead(x) {
        this.head_ = x;
    }
    setTail(x) {
        this.tail_ = x;
    }
    equals(other) {
        if (typeof other !== 'object') {
            console.log(other, 'EEP');
            return false;
        }
        if (!(other instanceof MyList)) {
            console.log(other, 'EEP');
            return false;
        }

        var h = this.head_;
        var ho = other.getHead();
        var cmp1 = comparatorof(h);
        if (!cmp1(h, ho)) {
            return false;
        }
        var t = this.tail_;
        var to = other.getTail();
        var cmp2 = comparatorof
        if (!cmp2(t, to)) {
            return false;
        }

        return true;
    }
}

var object1 = {
    0: "one",
    1: "two",
    2: ["one", "two", []],
    something: {
        1: [false, true]
    }
};

function strictComparator(a, b) {
    return a === b;
}

// given any object, tries finding a function for comparing 
// that object to objects of the same kind. Kind being
// used loosely, since some objects like null resist being categorized,
// so these objects need special alteration of the comparatorof itself.
function comparatorof(x) {
    if (x === null || x === undefined) {
        return strictComparator;
    }

    x = Object(x); // promote primitives to objects
    var ctor = x.constructor;
    var c2ct = ctorToComparatorTable;
    var n = c2ct.length;

    for (var i = 0; i < n; ++i) {
        var record = c2ct[i];
        var keyCtor = record[0];

        if (keyCtor === ctor) {
            return record[1];
        }
    }
    throw new TypeError('no comparator exists for ' + x);
}

var ctorToComparatorTable = [
    [String, function(a, b) {
        return a == b;
    }],
    [Object, function(a, b) {
        for (var key in a) {
            var avalue = a[key];
            var bvalue = b[key];
            var cmp = comparatorof(avalue);

            if (!cmp(avalue, bvalue)) {
                return false;
            }
        }

        return true;
    }],
    [Number, function(a, b) {
        return a == b;
    }],
    [Boolean, function(a, b) {
        return a == b;
    }],
    [Array, function(as, bs) {
        if (typeof bs !== 'object') {
            return false;
        }
        var nAs = as.length;
        var nBs = bs.length;

        if (nAs !== nBs) {
            return false;
        }

        for (var i = 0; i < nAs; ++i) {
            var a = as[i];
            var b = bs[i];
            var cmp = comparatorof(a);

            if (!cmp(a, b)) {
                return false;
            }
        }

        return true;
    }],
    [MyList, function(a, b) {
        return a.equals(b);
    }]
];

// true
console.log(comparatorof([])([new MyList(1, new MyList(2, 3))], [new MyList(1, new MyList(2, 3))]));
// true
console.log(comparatorof([])([{}, new MyList(1, new MyList(2, 3))], [{}, new MyList(1, new MyList(2, 3))]));
// false
console.log(comparatorof([])([{}, new MyList(1, new MyList(2, 3))], [{}, new MyList(1, new MyList(3, 3))]));
// true
console.log(comparatorof({})({
    1: 'one',
    one: '1',
    x: new MyList(1, {})
}, {
    1: 'one',
    one: '1',
    x: new MyList(1, {})
}));
// true
console.log(comparatorof(2)(
    3,
    3
));
//true
console.log(comparatorof(true)(
    true,
    true
));
//false
console.log(comparatorof([])(
    [1, 2, new MyList(1, 2)], [1, 2, new MyList(4, 9)]
));
// true
console.log(comparatorof([])(
    [1, 2, new MyList(1, 2), null], [1, 2, new MyList(1, 2), null]
));
// false
console.log(comparatorof(null)(
    null,
    undefined
));
// true
console.log(comparatorof(undefined)(
    undefined,
    undefined
));
// true
console.log(comparatorof(null)(
    null,
    null
));

Ein großes Problem ist, dass ES6 bereits voller Funktionen ist, die mit JScript und Nashorn JJS sowie ActionScript inkompatibel sind, dass die Sprache alle paar Monate als eine ganz neue Sprache umbenannt werden kann, wenn man bedenkt, dass man das effektiv bekommt, wenn man neue hinzufügt Features zu einer Sprache, die die Kompatibilität mit alten Versionen davon brechen, die nicht ohne eine zusätzliche Evaluierungsschicht repliziert werden können.

Dieses Problem reicht lange zurück, wo Sie einerseits eine minimale Sprache wie Lisp haben, die “einfacher” ist (den Operator “‘ immer noch nicht überladen kann), um “erstklassige” Funktionen einzuführen, ohne die Abwärtskompatibilität zu brechen, und dann haben Sie Sprachen wie Perl, das ohne eine zusätzliche Evaluierungsschicht nicht mit neuen erstklassigen Schlüsselwörtern erweitert werden kann. JavaScript wählte den zweiten Ansatz und umgeht im Allgemeinen die Konsequenzen, indem es Hilfsobjekte wie Math, Object verwendet, um neue Funktionen einzuführen, aber jedes Mal, wenn es “erstklassige Konstrukte” hinzufügen möchte, bricht es die Abwärtskompatibilität.

Als Machbarkeitsnachweis können Sie in Lisp den ==-Operator überladen, während dies in JavaScript nicht möglich ist und in Perl nur durch einen Mechanismus, der Schlüsselwörter reserviert.

1647262512 321 Warum funktioniert die Gleichheitsprufung nicht mit Arrays duplicate
Ank_247shbm

Wenn ich dieses Problem damit in Python beziehe:

Eingang:

a="1 2 3 4"

Fall I:

a=input.split(' ')

Ausgang: [‘1’, ‘2’, ‘3’, ‘4’]

Fall II:

a=map(int,input.split(' '))

Ausgang: [1, 2, 3, 4]

Der Fehler ist also der Typ, da er als “wahr” herauskommen könnte für:

"1:2".split(':').toString() == [1,2].toString(); //true

  • Bitte teilen Sie weitere Details mit. Da es bei dieser Frage um Javascript geht, wie bezieht sich Ihre Antwort darauf?

    – Nico Haase

    3. Februar um 13:06 Uhr

1001620cookie-checkWarum funktioniert die Gleichheitsprüfung nicht mit Arrays? [duplicate]

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

Privacy policy