lodash: mapowanie tablicy na obiekt


90

Czy istnieje wbudowana funkcja lodash, aby to zrobić:

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

I wypisz to:

var output = {
    foo: 'bar',
    baz: 'zle'
};

W tej chwili po prostu używam Array.prototype.reduce() :

function toHash(array, keyName, valueName) {
    return array.reduce(function(dictionary, next) {
        dictionary[next[keyName]] = next[valueName];
        return dictionary;
    }, {});
}

toHash(params, 'name', 'input');

Zastanawiam się, czy istnieje skrót lodash.

Odpowiedzi:


132

Inny sposób z lodash 4.17.2

_.chain(params)
    .keyBy('name')
    .mapValues('input')
    .value();

lub

_.mapValues(_.keyBy(params, 'name'), 'input')

lub z _.reduce

_.reduce(
    params,
    (acc, { name, input }) => ({ ...acc, [name]: input }),
    {}
)

@Akrikos _.keyByprzekształci całą tablicę w obiekt, podczas gdy pytanie dotyczy głównie posiadania jednego elementu z każdego obiektu w tablicy jako klucza i jednego innego elementu jako jego wartości. Jeśli _.keyByzostanie użyte, wszystkie wartości będą obiektami.
Mustafa Ehsan Alokozay

Dzięki @MustafaEhsanAlokozay Masz rację, ta odpowiedź nie jest właściwa. Usunę mój komentarz, ponieważ nie jest pomocny. To może sprawić, że twój komentarz będzie wyglądał dziwnie, ale lepiej, niż gdyby mój niepoprawny komentarz pozostał dłużej.
Akrikos

53

Powinieneś używać _.keyBy, aby łatwo przekonwertować tablicę na obiekt.

Dokumenty tutaj

Przykładowe użycie poniżej:

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
console.log(_.keyBy(params, 'name'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

W razie potrzeby możesz manipulować tablicą przed użyciem _.keyBy lub obiektem po użyciu _.keyBy, aby uzyskać dokładnie pożądany wynik.


2
Spójrz najpierw na to, aby zrozumieć większość odpowiedzi, na które głosował Stasovlas.
Roman Susi,

3
To fajna odpowiedź, ale NIE odpowiada na pytanie. Wartości powinny być łańcuchami, a nie obiektami.
Dem Pilafian

34

Tak, jest tutaj , używając_.reduce

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

_.reduce(params , function(obj,param) {
 obj[param.name] = param.input
 return obj;
}, {});

Po raz kolejny reduce()pojawia się inny przypadek użycia. Sprytny sposób na zrobienie tego!
Dan

Czy ktoś ma wersję na maszynie?
pan Bjerre

W rzeczywistości jest to matematycznie prawdziwe, że można zaimplementować dosłownie dowolną akcję iteracji za pomocą funkcji redukuj / wstrzykuj, ponieważ redukcja jest izomorficzna z listą. Jednak ta elastyczność ma swoją cenę w czytelności. Nie używaj, _.reducechyba że dokładnie oddaje to, co próbujesz zrobić: w każdym innym przypadku znacznie przesłania sens kodu. Osobiście wolę _.zipObjectrozwiązanie @djechlin - w przeciwnym razie _.keyBy/ _.mapValuespodejście.
Robert Fischer

15

Wygląda na to, że jest to zadanie dla Object. assign:

const output = Object.assign({}, ...params.map(p => ({[p.name]: p.input})));

Edytowany do zawijania jako funkcja podobna do OP, wyglądałaby tak:

const toHash = (array, keyName, valueName) => 
    Object.assign({}, ...array.map(o => ({[o[keyName]]: o[valueName]})));

(Dzięki Benowi Stewardowi, dobre myślenie ...)


Może zawiń to w funkcję nadrzędną, aby użytkownik mógł określić, jakie klucze będą używane, przekazując je, tak jak w przypadku OP.
Ben Steward


10

Jest to prawdopodobnie bardziej szczegółowe niż chcesz, ale prosisz o nieco złożoną operację, więc może być zaangażowany rzeczywisty kod (horror).

Moje zalecenie, z zipObjecttym całkiem logiczne:

_.zipObject(_.map(params, 'name'), _.map(params, 'input'));

Inna opcja, bardziej hackerska, używając fromPairs:

_.fromPairs(_.map(params, function(val) { return [val['name'], val['input']));

Funkcja anonimowa pokazuje hacking - nie wierzę, że JS gwarantuje kolejność elementów w iteracji obiektu, więc callling .values()nie wystarczy.


Nie widzę nic dziwnego w używaniu fromPairs, a dzwonienie values()rzeczywiście nie wystarczy. Przynajmniej z punktu widzenia czytelności.
x-yuri

6

Inny sposób z lodash

tworząc pary, a następnie konstruuj obiekt lub ES6 Mapłatwo

_(params).map(v=>[v.name, v.input]).fromPairs().value()

lub

_.fromPairs(params.map(v=>[v.name, v.input]))

Oto działający przykład


1
Object.fromEntries(params.map(v => [v.name, v.input]))
Zaletą

@fregante, Chrome 73+, tylko caniuse.com/?search=fromEntries
d9k

6

Może również rozwiązać problem bez użycia funkcji lodash, takiej jak ta:

let paramsVal = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
let output = {};

paramsVal.forEach(({name, input})=>{
  output[name] = input;
})


console.log(output);

wprowadź opis obrazu tutaj

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.