2016-05-10 4 views
1

für ein aktuelles Projekt, ich arbeite mit einer API, die Daten formatiert wie folgt zurückgibt:Gibt es eine einfache Möglichkeit, verschachtelte Daten mit Lodash zu verknüpfen?

{ 
    groups: [ 
    { 
     items: [ 
     { 
      points: [ 
      { name: "name1", ... }, 
      { name: "name2", ... }, 
      { name: "name3", ... }, 
      ... 
      ], 
      ... 
     }, 
     ... 
     ] 
    }, 
    ... 
    ], 
    ... 
}; 

Ich mag würde eine reine Funktion, schaffen mapValues, die in der oben in einem Objekt nimmt format, sowie ein Objekt, das jede name auf eine value abbildet und die gleiche Struktur zurückgibt, aber mit jeder point, die die value enthält, die ihrer name entspricht.

Zum Beispiel rufen mapValues(data, { name1: "value1", name2: "value2", name3: "value3" }) soll dies zurück:

{ 
    groups: [ 
    { 
     items: [ 
     { 
      points: [ 
      { name: "name1", value: "value1", ... }, 
      { name: "name2", value: "value2", ... }, 
      { name: "name3", value: "value3", ... }, 
      ... 
      ], 
      ... 
     }, 
     ... 
     ] 
    }, 
    ... 
    ], 
    ... 
}; 

Hier ist mein erster Pass:

function mapValues(data, values) { 
    return _.extend({}, data, { 
    groups: _.map(ui.groups, (group) => { 
     return _.extend({}, group, { 
     items: _.map(group.items, (item) => { 
      return _.extend({}, item, { 
      points: _.map(item.points, (point) => { 
       return _.extend({ value: values[point.name] }, point); 
      }) 
      }); 
     }) 
     }); 
    }) 
    }); 
} 

das funktioniert, aber es ist schon ein bisschen einen doppelten Code der Verschachtelung. Für meinen zweiten Versuch griff ich zur Rekursion.

function mapValues(data, values) { 
    return (function recursiveMap(object, attributes) { 
    if (attributes.length === 0) { return _.extend({ value: values[object.name] }, object); } 
    let key = attributes[0]; 
    return _.extend({}, object, { 
     [key]: _.map(object[key], child => recursiveMap(child, attributes.slice(1))) 
    }); 
    })(ui, ["groups", "items", "points"]); 
} 

Das funktioniert auch, aber es ist schwer zu lesen und nicht sehr prägnant.

Gibt es eine sauberere Möglichkeit, ein Objekt mithilfe von Lodash rekursiv zuzuordnen? Im Idealfall suche ich nach einem funktionellen Ansatz.

Antwort

0

Ich weiß, Sie wollten Lodash, aber ich hatte vor einiger Zeit gleiche Problem und ich habe kam mit diesem JSFiddle ich großes Werkzeug von nervgh erstellt verwende. Es ist sehr einfach, aber nützlich. Sie können diese Funktion so einstellen, dass sie rein ist, indem Sie Object.assign verwenden, Schlüsselparameter akzeptieren und sie wie gewünscht verändern. Du hast die Idee.

function mapValues(data, values) { 
    var iterator = new RecursiveIterator(data); 
    for(let {node} of iterator) { 
    if(node.hasOwnProperty('name')) { 
     node.value = values[node.name]; 
    } 
    } 
    return data; 
} 
+0

Danke für die Antwort! Ich mag das Konzept eines rekursiven Iterators, aber diese Lösung scheint die Werte an Ort und Stelle zu ändern, und ich habe auf eine reine, funktionale Lösung gehofft. Mit rein, meine ich das: https://en.wikipedia.org/wiki/Pure_function – LandonSchropp

+0

Sie können immer 'Object.assign' verwenden, um zu vermeiden, Datenobjekt mutieren und Iterator dieses" kopierten "Objekts erstellen und dann zurückgeben. –

1

Hier ist eine Art und Weise Sie es Object.assign und keine Lust Funktionen tun können

var data = <your data here>; 
var values = <your mapped values>; 

data.groups.items.points.map(p=> 
    Object.assign(p, {value: values[p.name]}) 
); 

pass by reference Dies funktioniert, weil Arrays und Objekte verwenden. Änderungen an den Werten führen dazu, dass das Original geändert wird.

Wenn Sie Ihr ursprüngliches Dataset nicht mutieren möchten, müssen Sie {} als erstes Argument verwenden (um ein neues, leeres Objekt zuzuweisen) und eindeutige Lese-/Schreibpfade für jedes Objekt anzeigen.

var newData = Object.assign({}, data, 
    {groups: 
    {items: 
     {points: data.groups.items.points.map(p=> 
     Object.assign({}, p, {value: values[p.name]}) 
    )} 
    } 
    } 
); 
+0

Danke für die Antwort! Ich denke, das Problem besteht darin, dass "Gruppen" und "Objekte" ebenfalls Arrays sind und Ihre Lösung diese als Objekte behandelt. – LandonSchropp