[英]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.