[英]JavaScript Equivalent of C# ToDictionary
我正在尋找一種方法來獲取以下列表:
directory = [
{
name: "Albert",
age: 40,
gender: "M"
},
{
name: "Suzanne",
age: 27,
gender: "F"
},
{
name: "Robert",
age: 19,
gender: "M"
},
{
name: "Connie",
age: 87,
gender: "F"
}
]
並在鍵name
上制作字典:
dictionary = {
"Albert": {
name: "Albert",
age: 40,
gender: "M"
},
"Suzanne": {
name: "Suzanne",
age: 27,
gender: "F"
},
"Robert": {
name: "Robert",
age: 19,
gender: "M"
},
"Connie": {
name: "Connie",
age: 87,
gender: "F"
}
}
這類似於 C# ToDictionary
方法。 我知道我可以在for
循環或.each
調用中迭代directory
,並在每次迭代中修改dictionary
的值。 但是,我更願意進行類似函數式編程的分配,例如
dictionary = directory.toDictionary(p => p.name);
在 ES6 或 lodash 中是否存在這樣的方法?
您可以映射鍵和值,並使用(即將推出的) Object.fromEntries
從這個數組創建一個對象。
var directory = [{ name: "Albert", age: 40, gender: "M" }, { name: "Suzanne", age: 27, gender: "F" }, { name: "Robert", age: 19, gender: "M" }, { name: "Connie", age: 87, gender: "F" }], result = Object.fromEntries(directory.map(o => [o.name, o])); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
經典方法
var directory = [{ name: "Albert", age: 40, gender: "M" }, { name: "Suzanne", age: 27, gender: "F" }, { name: "Robert", age: 19, gender: "M" }, { name: "Connie", age: 87, gender: "F" }], result = Object.assign({}, ...directory.map(o => ({ [o.name]: o }))); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Javascript 的Map
非常類似於字典。 它的實例has
, get
, set
, keys
, values
方法。 它也可以通過forEach
方法直接迭代。
您可以使用“鍵值對”數組構建Map
。 (在引號中,因為實際上我們以某種類似元組的方式使用數組)。
要創建用作字典的Map
,您可以執行以下操作:
const directory=[{name:"Albert",age:40,gender:"M"},{name:"Suzanne",age:27,gender:"F"},{name:"Robert",age:19,gender:"M"},{name:"Connie",age:87,gender:"F"}]; const myDict = new Map( directory.map(p => [p.name, p]) ); console.log("Has Albert:", myDict.has("Albert")) myDict.forEach(p => { console.log(`${p.name} has age ${p.age}`) });
你可以reduce
數組。 使用Object.assign()
將每個名稱添加為屬性
const directory=[{name:"Albert",age:40,gender:"M"},{name:"Suzanne",age:27,gender:"F"},{name:"Robert",age:19,gender:"M"},{name:"Connie",age:87,gender:"F"}], output = directory.reduce((r, o) => Object.assign(r, { [o.name]: o }), {}) console.log(output)
由於您也詢問了lodash
解決方案,您可以使用該庫的.keyBy()方法。
const directory = [{name:"Albert",age:40,gender:"M"},{name:"Suzanne",age:27,gender:"F"},{name:"Robert",age:19,gender:"M"},{name:"Connie",age:87,gender:"F"}]; console.log(_.keyBy(directory, o => o.name));
.as-console {background-color:black !important; color:lime;} .as-console-wrapper {max-height:100% !important; top:0;}
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.14/lodash.min.js"></script>
但是,正如我在評論中所說,第一個結構允許多個同名條目,而結果則不允許。 因此,在directory
數組包含多個同名對象的情況下,您將只會在結果數據中獲得最后一個。
沒有特定的內置功能,但使用.reduce()
很容易:
let dict = directory.reduce((d, v) => (d[v.name] = v, d), {});
正如對該問題的良好評論所指出的那樣,您需要考慮的一件事是重復名稱的含義。 這是“壞數據”的情況嗎? 這種重復是否應該有一系列名稱? 諸如此類的問題特定於數據結構及其在您的特定應用程序中的用途。
下面是我如何添加 ToDictionary 的實現,它允許您也定義一個鍵選擇器,並允許每個鍵重復值,如果有很多值,這些值將保存到一個數組中。 該方法是我在 Npmjs.com 上托管的庫“simpletslinq”的 1.0.14 版的一部分
請注意,我的代碼是用 Typescript 編寫的,因此您必須在其上運行 tsc typescript 編譯器才能創建真正的 Javscript 等效項。 在其核心,我們使用 map 函數來創建字典。 添加的打字稿東西是添加類型檢查..
if (!Array.prototype.ToDictionary) {
Array.prototype.ToDictionary = function <T>(keySelector: (arg: T) => any): any {
let hash = {};
this.map(item => {
let key = keySelector(item);
if (!(key in hash)) {
hash[key] = item;
}
else {
if (!(Array.isArray(hash[key]))) {
hash[key] = [hash[key]];
}
hash[key].push(item);
}
});
return hash;
}
}
此代碼的規范(測試)如下所示:
it('can apply method ToDictionary on an array, allowing specificaton of a key selector for the dictionary object', () => {
let heroes = [{ name: "Han Solo", age: 47, gender: "M" }, { name: "Leia", age: 29, gender: "F" }, { name: "Luke", age: 24, gender: "M" }, { name: "Lando", age: 47, gender: "M" }];
let dictionaryOfHeroes = heroes.ToDictionary<Hero>(x => x.gender);
let expectedDictionary = {
"F": {
name: "Leia", age: 29, gender: "F"
},
"M": [
{ name: "Han Solo", age: 47, gender: "M" },
{ name: "Luke", age: 24, gender: "M" },
{ name: "Lando", age: 47, gender: "M" }
]
};
expect(dictionaryOfHeroes).toEqual(expectedDictionary);
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.