wake-up-neo.com

Entfernen Sie doppelte Objekte aus dem JSON-Array

Ich habe ein Array, das so aussieht:

var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];

Und ich muss die Duplikate entfernen, damit so etwas bleibt:

var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];

Ich habe versucht, Underscore.js zu installieren und ._uniq zu verwenden, aber das scheint nur zu funktionieren, wenn ein einzelnes key:value-Paar im Objekt erscheint. Ich kann nicht scheinen, dass es über mehrere Tasten hinweg funktioniert. 

Wenn ich so etwas versuche:

var uniqueStandards = _.uniq(standardsList, function(item, key, Domain){
    return item.Domain;
});

Ich bekomme nur die ersten drei eindeutigen Werte (einen pro Klasse). Aber ich brauche alle eindeutigen Werte sowohl für die Klasse als auch für die Domäne. Gibt es eine einfache Möglichkeit, beide Schlüssel der _.uniq-Funktion zuzuführen?

Letztendlich brauche ich eine Liste mit jeder eindeutigen Note als Kopfzeile und den eindeutigen Domänen als Listenelementen, die in eine HTML-Seite übergehen. Ich gehe vielleicht falsch herum. Wenn es also einen einfacheren Weg gibt, dieses Ziel zu erreichen, bin ich offen für Ideen. 

Danke im Voraus!

Edit: Einige gute Antworten bekommen und wollten klären, was mein Endziel war. Ich versuche, eine Reihe von Listen in HTML des Formulars zu erstellen:

<div>
    <h3>Math K</h3>
    <li>Counting & Cardinality</li>
    <li>Geometry</li>
</div>
<div>
    <h3>Math 1</h3>
    <li>Counting & Cardinality</li>
    <li>Orders of Operation</li>
</div>
<div>
    <h3>Math 2</h3>
    <li>Geometry</li>
</div>

Mein Original war jedoch, ein Array zu erstellen und dieses mit $("#divid").append(array) in das <div>-Element der Seite zu schieben

27
dchess

Letztendlich brauche ich eine Liste mit jeder eindeutigen Note als Kopfzeile und den eindeutigen Domänen als Listenelementen, die in eine HTML-Seite übergehen. Ich gehe vielleicht falsch herum. Wenn es also einen einfacheren Weg gibt, dieses Ziel zu erreichen, bin ich offen für Ideen.

Sie benötigen das Ausgabearray also nicht in dem Format, nach dem Sie gefragt haben.

Da dies der Fall ist, würde ich mit einer sehr einfachen und effizienten Lösung direkt auf die Jagd gehen:

var grades = {};
standardsList.forEach( function( item ) {
    var grade = grades[item.Grade] = grades[item.Grade] || {};
    grade[item.Domain] = true;
});

console.log( JSON.stringify( grades, null, 4 ) );

Das resultierende grades-Objekt lautet:

{
    "Math K": {
        "Counting & Cardinality": true,
        "Geometry": true
    },
    "Math 1": {
        "Counting & Cardinality": true,
        "Orders of Operation": true
    },
    "Math 2": {
        "Geometry": true
    }
}

Eine interessante Sache über diesen Ansatz ist, dass er sehr schnell ist. Beachten Sie, dass das Eingabearray nur einen einzigen Durchlauf durchläuft, im Gegensatz zu anderen Lösungen, für die mehrere Durchläufe erforderlich sind (unabhängig davon, ob Sie sie selbst schreiben oder ob _.uniq() dies für Sie tut). Für eine kleine Anzahl von Elementen spielt dies keine Rolle, aber für größere Listen ist es gut, dies zu berücksichtigen.

Und mit diesem Objekt haben Sie jetzt alles, was Sie benötigen, um Code auszuführen oder ein beliebiges anderes Format zu generieren. Wenn Sie beispielsweise das von Ihnen erwähnte exakte Array-Ausgabeformat benötigen, können Sie Folgendes verwenden:

var outputList = [];
for( var grade in grades ) {
    for( var domain in grades[grade] ) {
        outputList.Push({ Grade: grade, Domain: domain });
    }
}

JSON.stringify( outputList, null, 4 );

Dies wird protokollieren:

[
    {
        "Grade": "Math K",
        "Domain": "Counting & Cardinality"
    },
    {
        "Grade": "Math K",
        "Domain": "Geometry"
    },
    {
        "Grade": "Math 1",
        "Domain": "Counting & Cardinality"
    },
    {
        "Grade": "Math 1",
        "Domain": "Orders of Operation"
    },
    {
        "Grade": "Math 2",
        "Domain": "Geometry"
    }
]

Rai fragt in einem Kommentar, wie diese Codezeile funktioniert:

var grade = grades[item.Grade] = grades[item.Grade] || {};

Dies ist ein allgemeiner Ausdruck für das Abrufen einer Objekteigenschaft oder das Bereitstellen eines Standardwerts, wenn die Eigenschaft fehlt. Beachten Sie, dass die =-Zuweisungen in der Reihenfolge von rechts nach links erfolgen. So könnten wir es wörtlich übersetzen, eine if-Anweisung und eine temporäre Variable zu verwenden:

// Fetch grades[item.Grade] and save it in temp
var temp = grades[item.Grade];
if( ! temp ) {
    // It was missing, so use an empty object as the default value
    temp = {};
}
// Now save the result in grades[item.Grade] (in case it was missing)
// and in grade
grades[item.Grade] = temp;
var grade = temp;

Möglicherweise stellen Sie fest, dass in dem Fall, in dem grades[item.Grade] bereits vorhanden ist, wir den gerade abgerufenen Wert übernehmen und in derselben Eigenschaft speichern. Dies ist natürlich unnötig und Sie würden es wahrscheinlich nicht tun, wenn Sie den Code so schreiben würden. Stattdessen würden Sie es vereinfachen:

var grade = grades[item.Grade];
if( ! grade ) {
    grade = grades[item.Grade] = {};
}

Dies wäre eine absolut sinnvolle Möglichkeit, denselben Code zu schreiben, und er ist auch effizienter. Es gibt Ihnen auch eine Möglichkeit, einen spezifischeren Test als die "Wahrheit" durchzuführen, auf die sich das ||-Idiom stützt. Anstelle von if( ! grade ) möchten Sie möglicherweise if( grade === undefined ) verwenden.

12
Michael Geary
function arrUnique(arr) {
    var cleaned = [];
    arr.forEach(function(itm) {
        var unique = true;
        cleaned.forEach(function(itm2) {
            if (_.isEqual(itm, itm2)) unique = false;
        });
        if (unique)  cleaned.Push(itm);
    });
    return cleaned;
}

var standardsList = arrUnique(standardsList);

GEIGE

Das wird wiederkommen

var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];

Welches ist genau das, wonach Sie gefragt haben?

21
adeneo

Ich weiß, dass es bereits viele Antworten gibt, aber die beste, die für eine komplexe Json-Struktur für mich gearbeitet hat, ist:

var arr = [{ "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RWCW", "desc": "WEST", "code": "RWCW", "level": 0, "save": "RWCW : WEST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RCSW", "desc": "SOUTHWEST", "code": "RCSW", "level": 0, "save": "RCSW : SOUTHWEST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RCNW", "desc": "MIDWEST", "code": "RCNW", "level": 0, "save": "RCNW : MIDWEST", "attribute1": "", "attribute2": "" }, { "State": "RSCW", "desc": "SOUTHEAST", "code": "RSCW", "level": 0, "save": "RSCW : SOUTHEAST", "attribute1": "", "attribute2": "" }, { "State": "RECW", "desc": "NORTHEAST", "code": "RECW", "level": 0, "save": "RECW : NORTHEAST", "attribute1": "", "attribute2": "" }];

var clean = arr.filter((arr, index, self) =>
    index === self.findIndex((t) => (t.save === arr.save && t.State === arr.State)))

console.log(clean);

Sie können dies direkt mit der Chrome-Browserkonsole versuchen und entsprechend Ihren Anforderungen bearbeiten.

Ich hoffe das hilft jemandem.

8
Aarchie

Eine alte Frage wiederbeleben, aber ich wollte eine Antwort auf die Antwort von @ adeneo posten. Diese Antwort ist völlig allgemein, aber für diesen Anwendungsfall könnte sie effizienter sein (sie ist auf meinem Computer mit einem Array von einigen tausend Objekten langsam). Wenn Sie die spezifischen Eigenschaften der Objekte kennen, die Sie vergleichen müssen, vergleichen Sie sie einfach direkt:

var sl = standardsList;
var out = [];

for (var i = 0, l = sl.length; i < l; i++) {
    var unique = true;
    for (var j = 0, k = out.length; j < k; j++) {
        if ((sl[i].Grade === out[j].Grade) && (sl[i].Domain === out[j].Domain)) {
            unique = false;
        }
    }
    if (unique) {
        out.Push(sl[i]);
    }
}

console.log(sl.length); // 10
console.log(out.length); // 5
7
James Irwin

Javascript-Lösung für Ihren Fall:

console.log(unique(standardsList));

function unique(obj){
    var uniques=[];
    var stringify={};
    for(var i=0;i<obj.length;i++){
       var keys=Object.keys(obj[i]);
       keys.sort(function(a,b) {return a-b});
       var str='';
        for(var j=0;j<keys.length;j++){
           str+= JSON.stringify(keys[j]);
           str+= JSON.stringify(obj[i][keys[j]]);
        }
        if(!stringify.hasOwnProperty(str)){
            uniques.Push(obj[i]);
            stringify[str]=true;
        }
    }
    return uniques;
}
5
juvian

Folgendes funktioniert für mich:

_.uniq(standardsList, JSON.stringify)

Dies wäre jedoch für sehr lange Listen wahrscheinlich langsam.

3
stubailo

** Die folgende Methode funktioniert so, wie Sie es möchten. Es filtert das Array basierend auf allen Eigenschaftswerten . **

    var standardsList = [
  { "Grade": "Math K", "Domain": "Counting & Cardinality" },
  { "Grade": "Math K", "Domain": "Counting & Cardinality" },
  { "Grade": "Math K", "Domain": "Counting & Cardinality" },
  { "Grade": "Math K", "Domain": "Counting & Cardinality" },
  { "Grade": "Math K", "Domain": "Geometry" },
  { "Grade": "Math 1", "Domain": "Counting & Cardinality" },
  { "Grade": "Math 1", "Domain": "Counting & Cardinality" },
  { "Grade": "Math 1", "Domain": "Orders of Operation" },
  { "Grade": "Math 2", "Domain": "Geometry" },
  { "Grade": "Math 2", "Domain": "Geometry" }
];

const removeDupliactes = (values) => {
  let concatArray = values.map(eachValue => {
    return Object.values(eachValue).join('')
  })
  let filterValues = values.filter((value, index) => {
    return concatArray.indexOf(concatArray[index]) === index

  })
  return filterValues
}
removeDupliactes(standardsList) 

Ergebnisse dies

[{Grade: "Math K", Domain: "Counting & Cardinality"}

{Grade: "Math K", Domain: "Geometry"}

{Grade: "Math 1", Domain: "Counting & Cardinality"}

{Grade: "Math 1", Domain: "Orders of Operation"}

{Grade: "Math 2", Domain: "Geometry"}] 
2
saiteja

Ich musste einige JSON-Objekte entfernen, also stolperte ich über diese Seite. Ich habe mich jedoch für die kurze ES6-Lösung entschieden (keine Notwendigkeit für externe Bibliotheken) und diese in Chrome Dev Tools Snippets ausführen:

const data = [ /* any list of objects */ ];
const set = new Set(data.map(item => JSON.stringify(item)));
const dedup = [...set].map(item => JSON.parse(item));
console.log(`Removed ${data.length - dedup.length} elements`);
console.log(dedup);
2
Nomaed
var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];          

 function uniqurArray(array){
                         var a = array.concat();
                        for(var i=0; i<a.length; i++) {
                            for(var j=i+1; j<a.length; j++) {
                                if(a[i].Grade === a[j].Grade){
                                    a.splice(j--, 1);
                                }
                            }
                        }

                        return a;
                    }

    uniqurArray(standardsList) // put this js in console and you get uniq object in array
1
shehzad lakhani

var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];

standardsList = standardsList.filter((li, idx, self) => self.map(itm => itm.Domain).indexOf(li.Domain) === idx)

document.write(JSON.stringify(standardsList))

hier ist ein funktionaler Weg, der viel einfacher ist

standardsList = standardsList.filter((li, idx, self) => self.map(itm => itm.domain).indexOf(li.domain) === idx)
0
Miguel Coder

Verwenden Sie diesen Pseudocode

var standardsList = [
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Counting & Cardinality"},
    {"Grade": "Math K", "Domain": "Geometry"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Counting & Cardinality"},
    {"Grade": "Math 1", "Domain": "Orders of Operation"},
    {"Grade": "Math 2", "Domain": "Geometry"},
    {"Grade": "Math 2", "Domain": "Geometry"}
];
var newArr =[]
for(var i in standardsList){
    newArr.Push(JSON.stringify(standardsList[i]))
}
var obj = {};
newArr= newArr.filter((item)=>{
    return obj.hasOwnProperty(item) ? false : (obj[item] = true);
})
standardsList.length = 0
for(var i in newArr){
    standardsList.Push(JSON.parse(newArr[i]))
}
console.log(standardsList)

Ich habe ein Beispiel-Array ausgewählt, das Ihrem ähnlich ist. Es ist einfacher, Objekte zu vergleichen, wenn Sie sie erst einmal angezogen haben. Dann müssen Sie nur noch Strings vergleichen.

0
ashish yadav

Hier ist ein kurzer Einzeiler mit es6!

const nums = [
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC9233F2015",
  "AC9233F2015",
  "AC9233F2015",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC8818E2",
  "AC8818E2",
  "AC8818E2",
  "AC8818E2",
  "AC9233F2015",
  "AC9233F2015",
  "AC9233F2015",
  "AC9233F2015",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC8818E2",
  "AC8818E2",
  "AC9233F2015",
  "AC9233F2015",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  "AC8818E2",
  "AC8818E2",
  "AC8818E2",
  "AC8818E2",
  "ACB098F25",
  "ACB098F25",
  "ACB098F25",
  "ACB098F25",
  "AC8818E2",
  "AC8818E2",
  "AC8818E1",
  "AC8818E1",
  "AC8818E1",
  ]

Set ist ein neues Datenobjekt, das in ES6 eingeführt wurde. Weil Sie mit Set nur eindeutige Werte speichern können. Wenn Sie ein Array übergeben, werden alle doppelten Werte entfernt.

export const $uniquenums = [...new Set(nums)].sort(); 
0
Gerd