2013-07-23 5 views
45

Ich bin durch die underscore docs gegangen, aber ich kann nicht scheinen, eine Methode (oder verschachtelte Methodenaufruf) zu finden, um die folgende Transformation zu tun:Underscore.js - Map Array von Schlüssel/Wert-Paaren zu einem Objekt - Ein Liner

Lassen sie uns sagen, dass ich die folgende Javascript-Array haben:

[{ "name" : "sEcho", "value" : 1},{ "name" : "iColumns", "value" : 12}, ... ] 

Und ich brauche es in das folgende Objekt zu transformieren:

{ 
     sEcho: 1, 
     iColumns: 12, 
     ... 
} 

ich Underscore.js aus einem Grund so ist es mit muss eine Einlage sein.

+1

Eine Zeile? '_.map (arr, Funktion (v, o) {o = {}; Rückgabe o [v.name] = v.value, o});' Nicht sicher, ob es einen kürzeren Weg gibt ... – elclanrs

+0

@elclanrs Das würde ein Array von Objekten erstellen.Sie wollen nur ein Objekt. –

+0

@AaditMShah: Richtig, ich habe dann falsch verstanden ... – elclanrs

Antwort

52

Da niemand geschrieben hat dies als Antwort, ich poste es, weil ich denke, es ist besser als Jan's answer. Es ist kürzer und sauberer ohne die Inline-Funktion.

_.object(_.pluck(data, 'name'), _.pluck(data, 'value')); 
+2

AFAICS Unterstreichung garantiert nicht explizit eine Reihenfolge von 'pluck's und' map's Ergebnis, also selbst wenn dies in aktuellen Browsern funktioniert, würde ich mich nicht darauf verlassen. Stellen Sie sich vor, wie schwer es wäre, einen Fehler zu finden, bei dem die Werte den falschen Schlüsseln zugeordnet sind. – peterp

+0

Was Sie sagen, ist wahr, aber ich werde nur feststellen, dass das OP nicht explizit die gleiche Reihenfolge angefordert. –

+0

Ich habe mir keine Gedanken über die Reihenfolge der Schlüssel-Wert-Paare in der Karte gemacht (AFAIK, da gibt es jetzt sowieso eine Garantie in JS), sondern Werte, die den falschen Schlüsseln zugeordnet sind. Irgendwann, in einem Browser, könnte das Zupfen der Namen * * eine andere Reihenfolge zurückgeben als das Auswählen der Werte, was Ihre Daten völlig durcheinander bringen und z.B. '{sEcho: 12, iColumns: 1}' anstelle des erwarteten Ergebnisses. Deshalb würde ich das Schlüsselwert-Mapping in einem einzigen Vorgang bevorzugen, wie 'reduce' oder' map' – peterp

27

Dies sollte es tun:

_.reduce(array, function(o, v){ 
    o[v.name] = v.value; 
    return o; 
}, {}); 

Als Einzeiler (du mich verarschen, oder?):

_.reduce(array,function(a,b){a[b.name]=b.value;return a},{}); 
+0

Warum summieren Sie die 'b.value' Werte? Warum nicht ein einfaches 'a [b.name] = b.value'? –

+0

@muistooshort Ich dachte, es sollte sie summieren, weiß nicht wirklich, warum xD – Esailija

+5

Ich sehe keine Summierung angefordert. Und wenn sie versuchen, mit einem Einzeiler clever zu sein (was könnte auch anders sein?), Dann könntest du ebenso offen über deinen Hass für die Betreuer reden und einen Komma-Operator einwerfen: '_ (a) .reduce (Funktion (m, h) {return m [h.name] = h.Wert, m}, {}) '. Heh. –

3
var a = [{ "name" : "sEcho", "value" : 1},{ "name" : "iColumns", "value" : 12} ]; 

var o = {}; _.each(a, function(e) { o[e.name] = e.value; }); 

console.log(o); 
// Object {sEcho: 1, iColumns: 12} 
6

Angenommen, Sie haben die folgende JavaScript-Array haben:

var list = [ 
    { 
     name: "sEcho", 
     value: 1 
    }, 
    { 
     name: "iColumns", 
     value: 12 
    }, 
    ... 
]; 

Sie können es in das Format y konvertieren ou wollen wie folgt:

var table = _.reduce(list, function (table, item) { 
    table[item.name] = item.value; 
    return table; 
}, {}); 

Es ist nicht ein Liner, aber ich glaube nicht, dass Sie buchstäblich einen Liner gemeint. Hast du?

Hier ist ein Motto, wenn Sie wirklich ein Motto hieß:

var t = _.reduce(list, function (t, i) { return t[i.name] = i.value, t; }, {}); 

Ja, andere die gleiche Antwort gegeben haben. Das liegt aber nur daran, dass die Antwort auf Ihre Frage so einfach ist.

6
var names = _.pluck(data, 'name'); 
var values = _.pluck(data, 'value'); 
var result = _.object(_.zip(names, values)); 
console.log(result); 
+2

+1 Obwohl es interessant zu beachten ist, dass man 3 separate, weniger bekannte, spezialisierte Methoden benötigt, um etwas in der gleichen Menge Code zu tun, die man mit einer relativ bekannten Methode (reduce) machen kann. – Esailija

58

Variation auf Sza's answer, die "Array von Paaren" Signatur von _.object mit:

_.object(_.map(data, function(x){return [x.name, x.value]})) 
+2

Schön! Speichern Sie sogar ein paar Tastenanschläge, wenn Sie Typoskript verwenden;) '_.Objekt (_. Karte (Daten, (x) => {zurück [x.name, x.value]}))' – parliament

+1

@ parliament oder coffeescript :-) –

+3

Auch das Beispiel von Sza funktioniert ohne die Zip-Datei (da das Objekt entweder ein einzelnes Array von Name/Wert-Paaren oder zwei verschiedene Arrays benötigt). Also könntest du '_.object (_pluck (Daten, 'Name'), _.pluck (Daten, 'Wert'))' – ShawnFumo

2

perfekte Ort zu verwenden reduzieren Ich denke:

_.reduce(ary, function(memo, obj){ memo[obj["name"]] = obj["value"]; return memo }, {});

+1

doh, in zu spät – user2240431

0
var arr = [{ "name" : "sEcho", "value" : 1},{ "name" : "iColumns", "value" : 12}] 

ES6

_.mapObject(_.indexBy(arr, 'name'), (v) => v.value) 

ES5

_.mapObject(_.indexBy(arr, 'name'), function (v) { return v.value; }) 

Diese Iterierten zweimal obwohl

Verwandte Themen