2016-07-13 7 views
0

Ich habe ein Array mit einem Schlüssel "Name" und "Punkte". Es kann mehrere Einträge für einen bestimmten Namen geben. Was wäre der ideale Weg, um ein neues Array mit Namen, Punkten und einem neuen Schlüsseltyp basierend auf Punkten zu bilden. Beispiel: Eingang:Traverse ein Array und die niedrigsten 2 Einträge für einen bestimmten Namen

[{"name":"A", "points": 9}, 
{"name":"A", "points": 5}, 
{"name":"A", "points": 4}, 
{"name":"A", "points": 1}, 
{"name":"A", "points": 3}, 
{"name":"A", "points": 6}, 
{"name":"B", "points": 5}, 
{"name":"B", "points": 1}, 
{"name":"B", "points": 2}, 
{"name":"B", "points": 3}] 

Lowest points - typeA 
Second lowest points - typeB 

Ausgang:

[{"name":"A", "points": 1, "type":"typeA"}, 
{"name":"A", "points": 3, "type":"typeB"}, 
{"name":"B", "points": 1, "type":"typeA"}, 
{"name":"B", "points": 2, "type":"typeB"}] 
+0

Wenn Sie die gewünschte Ausgabe unterschiedliche Anzahl von Zeilen als der Eingang hat , lodash hilft dir nicht viel. Der Standard für den Zyklus wäre dein Freund hier. – libik

+0

@libik Ich habe die Frage für die Verwendung von normalen Traversal bearbeitet, die optimal sein sollte, da die Liste etwa 1000-2000 lang sein könnte – Nisha

Antwort

0

denke ich, dass dies eine gute Lösung wäre:

const input = [{"name":"A", "points": 9}, 
       {"name":"A", "points": 5}, 
       {"name":"A", "points": 4}, 
       {"name":"A", "points": 1}, 
       {"name":"A", "points": 3}, 
       {"name":"A", "points": 6}, 
       {"name":"B", "points": 5}, 
       {"name":"B", "points": 1}, 
       {"name":"B", "points": 2}, 
       {"name":"B", "points": 3}]; 

//this function will be passed to Array's "reduce" function, and will return the item with the lowest points 
const reduceLowest = (lowest, current) => current.points < lowest.points ? current : lowest; 

//this function receives an item and returns a new item with an additional "type" property 
const addType = (item, typeToAdd) => { return { name : item.name, points : item.points, type : typeToAdd } }; 

//this function receives an array and returns another array with its two lowests items (typeA and typeB) 
const returnTypeATypeB = (arr) => { 

    var lowestTypeA = arr  
     .reduce(reduceLowest) //gets the lowest item 
     ; 

    var lowestTypeB = arr 
     .filter((item) => item != lowestTypeA) //removes the item that already is the lowest from the array  
     .reduce(reduceLowest) //gets the lowest item 
     ; 

    //return an array containing the typeA and typeB items 
    return [ addType(lowestTypeA, "typeA"), addType(lowestTypeB, "typeB")]; 

};   

const output = 
    returnTypeATypeB(
     input.filter((item) => item.name === "A") 
    ) //gets typeA and typeB from the items which contains the name "A" 
    .concat(//concat the previous list with.. 
     returnTypeATypeB(
      input.filter((item) => item.name === "B") 
     ) //typeA and typeB from the items which contains the name "B" 
    ); 

console.log(output); 
//prints.. 
// [ { name: 'A', points: 1, type: 'typeA' }, 
// { name: 'A', points: 3, type: 'typeB' }, 
// { name: 'B', points: 1, type: 'typeA' }, 
// { name: 'B', points: 2, type: 'typeB' } ] 
+0

@demarchid Danke für die Idee. Ich habe tatsächlich nach Namen und dann nach Punkten sortiert. Dann schnitten die ersten 2 jedes Namens und fügte Art entsprechend hinzu. Musste es verallgemeinern, da die Liste groß ist, nicht nur A n B. – Nisha

+0

Gibt es ein npm-Modul für Objekt-Array, natürliche Sortierung basierend auf 2 Schlüsseln – Nisha