2013-07-23 16 views
45

Przechodzę przez underscore docs, ale nie mogę znaleźć metody (lub zagnieżdżone wywołanie metody), aby wykonać następujące przekształcenie:Underscore.js - Mapa Array par klucz/wartość do obiektu - Jedna linijka

Powiedzmy mam następującą tablicę javascript:

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

I muszę przekształcić go w następujący obiektu:

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

używam underscore.js bez powodu więc musi być być jednym liniowym.

+1

jednej linii? '_.map (arr, function (v, o) {o = {}; return o [v.name] = v.value, o});' Nie wiem, czy jest krótszy sposób to zrobić ... – elclanrs

+0

@elclanrs Który tworzyłby tablicę obiektów.Potrzebujesz tylko jednego obiektu. –

+0

@AaditMShah: Tak, źle to zrozumiałem ... – elclanrs

Odpowiedz

52

Ponieważ nikt nie opublikował to jest odpowiedź, publikuję ją, ponieważ uważam, że jest lepsza niż Jan's answer. Jest krótszy i czystszy bez funkcji wstawiania.

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

podkreślenie AFAICS nie gwarantuje w wyraźny sposób żadnej kolejności wyników "pluck" i 'map', więc nawet jeśli działa to w obecnych przeglądarkach, nie będę na nich polegać. Wyobraź sobie, jak trudno byłoby wyśledzić błąd, w którym wartości są przypisane do niewłaściwych kluczy. – peterp

+0

To, co mówisz, jest prawdą, ale zwrócę uwagę, że PO nie zażądał wyraźnie tego samego zamówienia. –

+0

Nie martwiłem się o kolejność par klucz-wartość na mapie (AFAIK, teraz jest to gwarancja w JS), ale raczej wartości przypisane do niewłaściwych kluczy. W niektórych przeglądarkach wyrywanie nazw * może * zwrócić kolejną kolejność niż wyskubywanie wartości, co całkowicie zepsuje dane i zwróci np. '{sEcho: 12, iColumns: 1}' zamiast oczekiwanego wyniku. Dlatego wolałbym sporządzać odwzorowanie klucz-wartość w pojedynczej operacji, takiej jak 'reduce' lub' map' – peterp

27

ten powinien zrobić:

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

Jako jedną wkładką (jesteś żartujesz, prawda?):

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

Dlaczego sumujesz wartości 'b.value'? Dlaczego nie prosty "a [b.name] = b.value"? –

+0

@muistooshort Myślałem, że to ma je podsumować, dunno naprawdę dlaczego xD – Esailija

+5

Nie widzę żadnego podsumowania wymagane. A jeśli starają się być sprytni przy pomocy jednego liniowca (z jakiego innego powodu?), Równie dobrze możesz rażąco mówić o swojej nienawiści do opiekunów i wrzucić operatora przecinka: _ _ (a) .reduce (funkcja (m, h) {return m [h.name] = h.value, 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

powiedzmy masz następującą tablicę JavaScript:

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

Możesz przekonwertować go do formatu y ou chcesz:

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

To nie jest jedna liniówka, ale nie sądzę, że dosłownie chodziło o jeden liniowiec. Czy ty?

Oto jeden liner jeśli naprawdę oznaczało jedno wyłożenie:

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

Tak, pod warunkiem, że inni samą odpowiedź. Ale to tylko dlatego, że odpowiedź na twoje pytanie jest tak prosta.

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

+1 Chociaż warto zauważyć, że potrzebujemy 3 osobnych, mniej znanych, specjalistycznych metod, aby zrobić coś w tej samej ilości kodu, co można zrobić przy użyciu jednej stosunkowo dobrze znanej metody (zmniejszyć). – Esailija

58

wariacja na Sza's answer, przy użyciu "tablicę par" podpisania _.object:

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

Nice! Nawet zapisać kilka naciśnięć klawiszy, jeśli używasz maszynopisu;) '_.object (_. Map (dane, (x) => {return [x.name, x.value]}))' – parliament

+1

@parliament lub coffeescript :-) –

+3

Również przykład Sza działałby bez zip (ponieważ obiekt przyjmuje jedną tablicę par nazwa/val lub dwie różne tablice). Możesz więc zrobić '_.object (_pluck (data, 'name'), _.pluck (data, 'value'))' – ShawnFumo

2

idealne miejsce do korzystania zmniejszyć myślę:

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

+1

doh, późnym – 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; }) 

This iteracje dwukrotnie chociaż