2017-02-12 2 views
5

Was ein elegent Weg ist - rein funktional, im Idealfall - zu verwandeln (reduzieren?) Dieses Array:Elegante Array Transformation in Javascript

var in = [ 
    { a: 1, b: 'x', c: 'foo' }, 
    { a: 1, b: 'y', c: 'goo' }, 
    { a: 2, b: 'x', c: 'hoo' }, 
    { a: 2, b: 'y', c: 'joo' } 
] 

In diesem:

var out = [ 
    { a: 1, x: 'foo', y: 'goo' }, 
    { a: 2, x: 'hoo', y: 'joo' } 
] 

Die Logik ist, dass alle Elemente sollten basierend auf ihrer a Eigenschaft verbunden werden, und alle b und c Eigenschaften bezeichnen Schlüssel/Wert-Paare jeweils, die auf der Grundlage ihrer gemeinsamen a Wert in das einzelne Objekt zusammengeführt werden sollten.

+0

Sie das letzte Element in der Menge aller Elemente mit dem gleichen 'a' Wert wollen? –

+0

Was ist Logik, um "out" abzuleiten? Hinweis, 'in' wirft' Uncaught SyntaxError: Unerwartetes Token in' – guest271314

+0

Ich habe die Logik in meiner Frage beschrieben, tut mir leid, dass ich das nicht im Voraus gesagt habe. –

Antwort

7

Sie können ein Hash-Objekt verwenden, und reduce das Hashing so zu wickeln:

const arr = [ 
 
    { a: 1, b: 'x', c: 'foo' }, 
 
    { a: 1, b: 'y', c: 'goo' }, 
 
    { a: 2, b: 'x', c: 'hoo' }, 
 
    { a: 2, b: 'y', c: 'joo' } 
 
]; 
 

 
let result = Object.values(   // the result is the values of the hash object 
 
    arr.reduce((hash, o) => {    // hash is a hash object that make it easier to group the result 
 
    hash[o.a] = hash[o.a] || {a: o.a}; // if there is no object in the hash that have the value of the key a equal to o.a, then create a new one 
 
    hash[o.a][o.b] = o.c;    // set the value of the key stored in o.b to o.c 
 
    return hash; 
 
    }, {}) 
 
); 
 

 
console.log(result);

+0

'forEach' ist wirklich nicht rein funktional. Das Reduzieren ist der richtige Weg. – Bergi

+2

@Bergi Ich habe gezögert. Ich werde die erste entfernen und die zweite behalten. Es ist mehr _elegant_ und darum bittet OP! –

+1

Jetzt für * das * erhalten Sie eine +1: D – Bergi

5

Sie einen Verschluss mit einem Map

var input = [{ a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' }], 
 
    output = input.reduce((map => (r, o) => (!map.has(o.a) && map.set(o.a, r[r.push({ a: o.a }) - 1]), map.get(o.a)[o.b] = o.c, r))(new Map), []); 
 

 
console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }
verwenden könnte

2

Sie können forEach und Object.assign verwenden, um nach a und dann map zu gruppieren, um Objektwerte zurückzugeben.

var data = [ 
 
    { a: 1, b: 'x', c: 'foo' }, 
 
    { a: 1, b: 'y', c: 'goo' }, 
 
    { a: 2, b: 'x', c: 'hoo' }, 
 
    { a: 2, b: 'y', c: 'joo' } 
 
] 
 

 
var r = {} 
 
data.forEach(e => r[e.a] = Object.assign((r[e.a] || {}), {a: e.a, [e.b]: e.c})) 
 
r = Object.keys(r).map(e => r[e]) 
 

 
console.log(r)

+0

Und beachte, dass 'Object.assign ((r [ea] || {}), {a: ea, [eb]: ec})' leicht zu '{... (r [ea] || abgekürzt werden kann {}), ... {a: ea, [eb]: ec}} 'unter Verwendung der Objektspreizungsnotation (und möglicherweise Babel, falls erforderlich). –

0

Nicht sicher, ob Ansatz elegant oder funktional, obwohl Renditen erwartete Ergebnis for..of Loops, Array.prototype.some() und Object.assign()

function props(array, key, prop1, prop2) { 
 
    let arr = []; 
 
    for (let obj of array) { 
 
    let o = {}; 
 
    for (let {[key]:_key, [prop1]:_prop1, [prop2]:_prop2} of [obj]) { 
 
     o[_prop1] = _prop2; 
 
     o[key] = _key; 
 
    } 
 
    if (!arr.some(p => p[key] === o[key])) arr.push(o); 
 
    for (let prop of arr) { 
 
     if (prop[key] == o[key]) { 
 
     prop = Object.assign(prop, o) 
 
     } 
 
    } 
 
    } 
 
    return arr 
 
} 
 

 
var _in = [ 
 
    { a: 1, b: 'x', c: 'foo' }, 
 
    { a: 1, b: 'y', c: 'goo' }, 
 
    { a: 2, b: 'x', c: 'hoo' }, 
 
    { a: 2, b: 'y', c: 'joo' } 
 
]; 
 

 
console.log(props(_in, "a", "b", "c"));

+0

Nein, das ist überhaupt nicht funktional. Und 'für (lassen Sie {[Taste]: _ Taste, [Prop1]: _ Prop1, [Prop2]: _ Prop2} von [Obj]) {' ist nur verrückt. – Bergi

0

I vorgesehen mag Antwort s, aber hier ist mein Versuch. Ich glaube, es ist besser lesbar, aber es nutzt Object.assign und Object.values

const input = [ 
    { a: 1, b: 'x', c: 'foo' }, 
    { a: 1, b: 'y', c: 'goo' }, 
    { a: 2, b: 'x', c: 'hoo' }, 
    { a: 2, b: 'y', c: 'joo' } 
] 

const map = input.reduce((acc, obj) => { 
    const [a, key, value] = Object.values(obj) 
    const newObj = {a, [key]: value} 

    if (acc[a]) { 
    Object.assign(acc[a], newObj) 
    } else { 
    acc[a] = newObj 
    } 

    return acc 
}, {}) 

console.log(Object.values(map)) 
Verwandte Themen