lodash: diziyi nesneye eşleme


93

Bunu almak için yerleşik bir lodash işlevi var mı:

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

Ve şunu çıktı:

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

Şu anda sadece kullanıyorum 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');

Bir lodash kestirmesi var mı merak ediyorum.

Yanıtlar:


138

Lodash ile başka bir yol 4.17.2

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

veya

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

veya ile _.reduce

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

@Akrikos _.keyBytüm diziyi bir nesneye dönüştürecektir, oysa soru çoğunlukla dizideki her nesneden bir öğenin anahtar olarak ve diğer bir öğenin değeri olarak alınmasıyla ilgilidir. Eğer _.keyBykullanılırsa, o zaman tüm değerler nesneler olacak.
Mustafa Ehsan Alokozay

Teşekkürler @MustafaEhsanAlokozay Haklısın, bu cevap doğru olanı yapmıyor. Yararlı olmadığı için yorumumu sileceğim. Bu, yorumunuzun tuhaf görünmesine neden olabilir, ancak yanlış yorumumun daha fazla kalmasını sağlamaktan daha iyidir.
Akrikos

55

Bir diziyi bir nesneye kolayca dönüştürmek için _.keyBy kullanıyor olmalısınız.

Dokümanlar burada

Aşağıdaki örnek kullanım:

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>

Gerekirse, _.keyBy kullanmadan önce diziyi veya _.keyBy'yi kullandıktan sonra nesneyi tam olarak istenen sonucu elde etmek için değiştirebilirsiniz.


2
Stasovlas tarafından en çok oylanan cevabı anlamak için önce buna bakın.
Roman Susi

5
Bu serin cevabı, ancak vermez DEĞİL soruya cevap. Değerler nesneler değil dizeler olmalıdır.
Dem Pilafian

34

Evet burada , kullanıyor_.reduce

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

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

Yine reduce()başka bir kullanım örneğiyle devreye girer. Bunu yapmanın akıllı yolu!
Dan

Bunun daktilo edilmiş sürümünü bilen var mı?
mr.bjerre

Gerçek şu ki, indirgeme bir liste için izomorfik olduğundan, herhangi bir yineleme eylemini azalt / enjekte kullanarak tam anlamıyla uygulayabileceğiniz matematiksel olarak doğrudur. Bununla birlikte, bu esneklik, okunabilirlikte bir bedelle birlikte gelir. _.reduceYapmaya çalıştığınız şeyi doğru bir şekilde ifade etmedikçe kullanmayın : Başka herhangi bir durumda kodun amacını önemli ölçüde gizler. Ben şahsen _.zipObjectçözümü @djechlin'i tercih ediyorum - başarısız olursa _.keyBy/ _.mapValuesyaklaşımı.
Robert Fischer

16

Bu, Object.assign için bir iş gibi görünüyor:

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

OP'lere benzer bir işlev olarak kaydırılacak şekilde düzenlendi, bu şöyle olacaktır:

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

(Ben Steward'a teşekkürler, iyi fikir ...)


Belki bunu bir üst işlev içine sarın, böylece kullanıcı, OP'nin yaptığı gibi, bunları geçirerek hangi anahtarların kullanılacağını belirleyebilir.
Ben Steward


10

Bu muhtemelen istediğinizden daha ayrıntılıdır, ancak biraz karmaşık bir işlem istiyorsunuz, bu yüzden gerçek kod dahil olabilir (korku).

Benim tavsiyem zipObjectoldukça mantıklı:

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

Başka bir seçenek, daha hacky, şunu kullanarak fromPairs:

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

Anonim işlev, bilgisayar korsanlığını gösterir - JS'nin nesne yinelemesinde öğelerin sırasını garanti ettiğine inanmıyorum, bu nedenle çağrı .values()yapmayacaktır.


Kullanmayla ilgili hileli bir şey görmüyorum fromPairsve aramak values()gerçekten işe yaramaz. En azından okunabilirlik açısından.
x-yuri

6

Lodash ile başka bir yol

çiftler oluşturun ve ardından bir nesne oluşturun veya ES6 Mapkolayca

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

veya

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

İşte çalışan bir örnek


1
Bu çözümün iyi yanı, düz ES için de uygulanabilir olmasıdır:Object.fromEntries(params.map(v => [v.name, v.input]))
fregante

@fregante, Chrome 73+ yalnızca caniuse.com/?search=fromEntries
d9k

6

Ayrıca, bunun gibi herhangi bir lodash işlevi kullanmadan da çözebilir:

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

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


console.log(output);

görüntü açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.