等效于C#ToDictionary的JavaScript

时间:2019-07-17 20:37:11

标签: javascript dictionary functional-programming

我正在寻找一种方法来列出以下列表:

    a function(){   
        promise<axiosResponse>().then(resp =>{ 
                console.log('1') 
                do this();  
                and this();
         })

             now do this function();
              console.log('2')  
     }

并在键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

这类似于C#ToDictionary方法。我知道我可以在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" } } 循环或directory调用中对for进行迭代,并在每次迭代中修改.each的值。但是,我宁愿进行类似函数式编程的赋值,例如

dictionary

例如在ES6或lodash中是否存在这种方法?

6 个答案:

答案 0 :(得分:4)

您可以映射键和值,并使用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; }

答案 1 :(得分:2)

JavaScript的Map与字典非常相似。它的实例使用方便的hasgetsetkeysvalues方法。也可以通过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}`) });

答案 2 :(得分:1)

您可以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)

答案 3 :(得分:1)

由于您也通过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数组包含多个具有相同名称的对象的情况下,您只会在结果数据上获取它们的最后一个。

答案 4 :(得分:0)

没有特定的内置函数,但是使用.reduce()很简单:

let dict = directory.reduce((d, v) => (d[v.name] = v, d), {});

正如在对该问题的评论中指出的那样,您需要考虑的一件事是重复名称的含义。那是“坏数据”的情况吗?这样的重复项应该有一个名称数组吗?诸如此类的问题是针对特定应用程序中数据结构及其用途的。

答案 5 :(得分:0)

如果使用Typescript编码,则Object.fromEntries要求调整库以允许ES2017或更高版本。请允许我提供一种替代方法,使用原型方法和Typescript进行编译时间检查和Intellisense。

这是一种扩展方法,可以借用C#中的术语。

首先在TS中定义一个接口方法:

   export { } //creating a module of below code 
   declare global {   type predicate<T> = (arg: T) => boolean;   interface Array<T> {
        ToDictionary<T>(keySelector: (arg: T) => string): any;
    }

然后在Array.protoype中添加方法ToDictionary:

    if (!Array.prototype.ToDictionary) {
  Array.prototype.ToDictionary = function <T>(keySelector: (arg: T) => string): any[] {
    let result = this.reduce((r, o) => Object.assign(r, { [keySelector(o)]: o }), {});
    return result;
  }
}

这是一个茉莉花规格(测试),可以对其进行测试:

    describe('Array Extensions tests for TsExtensions Linq esque library', () => {

  it('can apply method ToDictionary on an array, allowing specificaton of a key selector for the dictionary object', () => {
    let heroes = [{ name: "Han Solo", age: 44, 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.name);

    let expectedDictionary = {
      "Han Solo": {
        name: "Han Solo", age: 44, gender: "M"
      },
      "Leia": {
        name: "Leia", age: 29, gender: "F"
      },
      "Luke": {
        name: "Luke", age: 24, gender: "M"
      },
      "Lando":
        { name: "Lando", age: 47, gender: "M" }
    };
    expect(dictionaryOfHeroes).toEqual(expectedDictionary);
  });

这在Angular 8“解决方案”中有效。以上基本上与@Adiga解决方案相同。