2017-07-25 3 views
3

Ich habe ein Array wie folgt:Entfernen von doppelten Objekten in einem Array, diejenigen mit einem maximalen Eigenschaftswert zu halten

const array=[ {id:0, quantity:1}, {id:1, quantity:2}, {id:0, quantity:4} ] 

mein Ziel so sein wird:

const array=[ {id:1, quantity:2}, {id:0, quantity:4} ] 

Die Reihenfolge des Objekts spielt keine Rolle, solange es die 'ID' mit der größeren Menge finden kann

Ich habe versucht, Filter + FindIndex, Karte + Filter, etc, aber ich habe Fehler gemacht. Ich brauche Hilfe.

Antwort

1

Hier gehen Sie.

const array=[ {id:0, quantity:1}, {id:1, quantity:2}, {id:0, quantity:4} ]; 
 

 
const arrayFiltered = []; 
 

 
array.forEach(obj => { 
 
    const item = arrayFiltered.find(thisItem => thisItem.id === obj.id); 
 
    if (item) { 
 
     if (item.quantity < obj.quantity) { 
 
      item.quantity = obj.quantity; 
 
     } 
 
     
 
     return; 
 
    } 
 
    
 
    arrayFiltered.push(obj); 
 
}); 
 

 
console.log(arrayFiltered);

+0

@Amav Geck, habe ich versucht, Ihre Lösung und es funktioniert, aber man ich ein bisschen verwirrt, wie es funktioniert. Kann ich Ihren Durchhang, Telegramm oder irgendetwas hinzufügen? Ich muss dich fragen –

+0

Wir erstellen ein leeres Array, 'arrayFiltered'. Im 'forEach' durchlaufen wir das' array'. Für jedes Element in 'array' schauen wir in' arrayFiltered' nach, ob wir ein Element mit derselben ID finden können. Wenn es existiert, nehmen wir dieses Objekt und machen die Eigenschaft "quantity" auf dem Objekt gleich der höheren der beiden. Wenn es nicht in 'arrayFiltered' existiert, schieben wir es rein. Hoffe, das hilft. –

4

Sie könnten eine Hash-Tabelle verwenden und überprüfen, ob ein Objekt mit den gleichen id in der Ergebnismenge ist. Wenn die tatsächliche Menge größer ist, weisen Sie das tatsächliche Objekt zu.

var array = [{ id: 0, quantity: 1 }, { id: 1, quantity: 2 }, { id: 0, quantity: 4 }], 
 
    hash = Object.create(null), 
 
    unique = array.reduce(function (r, o) { 
 
     if (!(o.id in hash)) { 
 
      hash[o.id] = r.push(o) - 1; 
 
      return r; 
 
     } 
 
     if (o.quantity > r[hash[o.id]].quantity) { 
 
      r[hash[o.id]] = o; 
 
     } 
 
     return r; 
 
    }, []); 
 
    
 
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }

+0

Ich bin schockiert, dass Sie nicht dafür gesorgt haben, dass der Hash implizit als Teil eines Closures um die Reduce-Funktion deklariert wird. –

+0

@torazaburo, es ist leichter zu verstehen. –

0

Können Sie mit Objekten arbeiten? Es gibt eine einfache Alternative mit diesem Code

const array = [{id:0, quantity:1}, {id:1, quantity:2}, {id:0, quantity:4}] 
const object = {} 
array.forEach((element) => { 
    object[element.id] = element 
}) 

Das einzige Problem ist, dass Sie das vorherige Element jedes Mal überschreiben Sie ein Element mit der gleichen ID gefunden.

+0

Ich benutze die Antwort, die @Arnav gab mir –

0

Lassen Sie uns zuerst alle IDs bekommen. Dann finden wir für jede eindeutige ID alle relevanten Objekte im Array (unter Verwendung von filter) und erhalten das Maximum aller ihrer quantity Eigenschaften.

function uniqByMax(arr) { 
    const ids = arr.map(elt => elt.id); 
    const uniqueIds = uniq(ids); 

    return uniqueIds.map(id => { 
    const matchingElts = arr.filter(elt => elt.id === id); 
    const quantities = matchingElts.map(elt => elt.quantity); 
    const quantity = Math.max(...quantities); 

    return {id, quantity}; 
    }); 
} 

Sie können irgendwo uniq aus dem Netz holen, oder eine Bibliothek verwenden, oder es selbst schreiben.

Hier ist ein weiterer Ansatz, die einen Filter mit Nebenwirkungen verwendet, wenn das Ihre Tasse Tee ist:

function uniqByMax(arr) { 
    return arr.filter(elt => { 
    const previous = arr.find(e2 => e2.id === elt.id); 
    if (previous === elt) return true; 
    previous.quantity = Math.max(previous.quantity, elt.quantity); 
    }); 
} 

Die Grundidee ist durch die Elemente in einer Schleife. Für jedes Element finden wir, ob es ein früheres Element mit der gleichen ID gibt. Wenn nicht, behalten Sie dieses Element bei (return true;); andernfalls aktualisieren Sie die Menge des früheren Elements, das wir behalten haben, mit dem Maximum seiner Menge und der Menge dieses Elements.

Im Interesse der Allgemeinheit, es könnte interessant sein, diese Funktion von der Unterkunft parametrisieren wir eindeutige Werte von, und die Art und Weise zu aktualisieren/kombinieren mehrere Elemente zu finden sind:

function uniqTransform(arr, prop, combine) { 
    return arr.filter(elt => { 
    const previous = arr.find(e2 => e2[prop] === elt[prop]); 
    if (previous === elt) return true; 
    combine(previous, elt); 
    }); 

Dann rufen wir dies mit

uniqTransform(arr, 'id', (a, b) => a.quantity = Math.max(a.quantity, b.quantity)); 

Oder wir könnten es durch die Verwendung einer anderen Funktion verallgemeinern weitere Elemente zu identifizieren, die das gleiche für uniqueifying Zwecke in Betracht gezogen werden sollen, die wir uniqueFunc nennen:

function uniqTransform(arr, uniqueFunc, combineFunc) { 
    return arr.filter(elt => { 
    const previous = arr.find(e2 => uniqueFunc(elt, e2)); 
    if (previous === elt) return true; 
    combineFunc(previous, elt); 
    }); 

Dann rufen wir dies mit

uniqTransform(
    arr, 
    (a, b) => a.id === b.id, 
    (a, b) => a.quantity = Math.max(a.quantity, b.quantity)); 
+0

Danke für die detaillierte Erklärung! –

Verwandte Themen