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.