2017-10-20 4 views
0

Ich versuche, die verschachtelten Objekte innerhalb von Elementen mit dem gleichen Schlüssel zu kombinieren.Kombinieren übereinstimmenden Objekt-Arrays

  • Suche ‚Top-Level‘ Werte, die doppelt vorhanden sind,
  • die duplizierten ‚Top-Level‘ Elemente in einem Objekt kombinieren (einschließlich ihrer Kinder.
  • Es sollte in den ‚Typ‘ Arrays keine doppelten Werte

versuchte ich es hier https://jsfiddle.net/Lpq6huvw/410/

Eingangsdaten:

[{ 
    "a": "Mon", 
    "type": [{ 
     "b": 1 
    }, { 
     "b": 3 
    }] 
}, { 
    "a": "Mon", 
    "type": [{ 
     "b": 2 
    }] 
}, { 
    "a": "Tue", 
    "type": [{ 
     "b": 40 
    }] 
}, { 
    "a": "Tue", 
    "type": [{ 
     "b": 50 
    }] 
}, { 
    "a": "Wed", 
    "type": [{ 
     "b": 30 
    }] 
}] 

In diesem Array:

[{ 
     "a": "Mon", 
     "type": [{ 
     "b": 1 
     }, { 
     "b": 3 
     }, 
     { 
     "b": 2 
     }] 
    }, 
    { 
     "a": "Tue", 
     "type": [{ 
     "b": 40 
     }, 
     { 
     "b": 50 
     }] 
    }, { 
     "a": "Wed", 
     "type": [{ 
     "b": 30 
     }] 
    }] 

ich versuchte darunter, die alle duplizierten Elemente als ein Objekt abbildet. Ich möchte jedoch, dass jeder unter seinem "Toplevel" Vorgänger abgebildet wird.

const z = _.uniqBy(_.filter(data.map(e=>e.a), v => _.filter(data.map(e=>e.a), v1 => v1 === v).length > 1)) 
const dupes = data.filter(itm => z.includes(itm.a)) 

const flat = _.flatMap(dupes, item => 
         _(item.type) 
          .map(v => ({b: v.b})) 
          .value() 
) 
+0

Werden die Eigenschaftsnamen werden immer die gleichen, mit nur Werte ändern? – nnnnnn

+0

Ja, sie werden gleich bleiben – Ycon

+1

* "Es sollte keine doppelten Werte innerhalb der 'type' Arrays" * - Meinst du, dass die Eingabe nie duplizierten 'type'-Werte, oder dass die Eingabe duplizieren kann, aber die Ausgabe sollte nicht? – nnnnnn

Antwort

2

ich persönlich schön finden Javascript in Funktionen eingebaut arbeiten, und scheinen einfacher als Funktionen einige lodash zu folgen.

z.

var data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2},{"b":3}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}]; 
 

 
    
 
var result = data.reduce((acc, val) => { 
 
    var found = acc.find((findval) => val.a === findval.a); 
 
    if (!found) acc.push(val) 
 
    else found.type = found.type.concat(
 
    val.type.filter((f) => !found.type.find((findval) => f.b === findval.b))); 
 
    return acc; 
 
}, []); 
 
    
 
console.log(result);

+0

Groß - minimale Implementierung. Nur ein wenig verwirrt darüber, warum Daten mit 'var a' benannt wurden, gibt es' a' zurück. Wie auch immer - es funktioniert! – Ycon

+0

'a' im Rücklauf ist der Akkumulator in reduzierter Funktion. Ich werde einige der Variablen umbenennen, um die Verwirrung zu vermeiden. – Keith

+0

FYI Ich kombiniere es mit dieser Lösung aus einer anderen Frage- https://StackOverflow.com/Questions/46845461 – Ycon

1

Hier ist eine Antwort w/o lodash:

function combine (input) { 
    const hash = input.reduce((result, current) => { 
    if (result[current['a']]) { 
     result[current['a']] = result[current['a']].concat(current['type']) 
    } else { 
     result[current['a']] = current['type'] 
    } 

    return result 
    }, {}) 

    return Object.keys(hash).map(key => { 
    return { 
     a: key, 
     type: hash[key] 
    } 
    }) 
} 
1

ES6: Sie können mit Array # iterieren reduzieren, werden die Elemente in eine Karte sammeln, und dann mit der in ein Array umwandeln zurück Spread-Syntax und Karte # Werte:

const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}]; 
 

 
const result = [...data.reduce((m, { a, type }) => { 
 
    const item = m.get(a) || { a, type: [] }; // use a Set to maintain uniqueness 
 
    
 
    item.type.push(...type); 
 
    
 
    return m.set(a, item); 
 
}, new Map).values()] 
 
.map(({ a, type }) => ({ // make types unique again 
 
    a, 
 
    type: [...type.reduce((m, o) => m.has(o.b) ? m : m.set(o.b, o), new Map).values()] 
 
})); 
 

 

 
console.log(result);

Lodash: Verwenden Sie _.groupBy(), um alle Objekte mit derselben a-Eigenschaft in einer Gruppe abzurufen. Ordnen Sie die Gruppen zu und führen Sie die einzelnen Gruppen zusammen, indem Sie _.mergeWith() verwenden und alle type Arrays zusammenführen. Machen Sie einen weiteren Durchgang mit Karte, um alle Objekte in type Arrays einzigartig zu machen.

const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}]; 
 

 

 
const result = _(data) 
 
    .groupBy('a') 
 
    .map((group) => _.mergeWith({}, ...group, ((objValue, srcValue, key) => 
 
    key === 'type' ? (objValue || []).concat(srcValue) : undefined 
 
))) 
 
    .map((obj) => Object.assign(obj, { type: _.uniq(obj.type) })) 
 
    .value(); 
 

 
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

+0

Thansk für diese - aber keiner scheint mehrere Elemente innerhalb der 'b' proprety zu zeigen. Könnten Sie chceck? – Ycon

+0

Das Lodash ist einzigartig. Ich habe den ES6 behoben. –

Verwandte Themen