代码之家  ›  专栏  ›  技术社区  ›  user3226932

javascript从对象数组创建字符串到对象数组的映射

  •  0
  • user3226932  · 技术社区  · 2 年前

    有没有办法使用map函数从下面例子中的数组创建映射(将字符串映射到数组)?不确定如何将对象附加到已存在的键,而不是覆盖已存在的内容

    匮乏 {"Germany": [{score: 1}], "Austria": [{score: 1}], "Switzerland": [{score: 2},{score: 3}]}

    得到 {"Germany": [{score: 1}], "Austria": [{score: 1}], "Switzerland": [{score: 3}]}

    let data = [
      {country: 'Germany', score: 1},
      {country: 'Austria', score: 1},
      {country: 'Switzerland', score: 2},
      {country: 'Switzerland', score: 3}
    ];
    
    let dictionary = Object.assign({}, ...data.map((x) => ({[x.country]: [{score: x.score}]})));
    
    
    3 回复  |  直到 2 年前
        1
  •  2
  •   Robby Cornelissen    2 年前

    处理起来相当简单 reduce() 一些 destructuring spread syntax :

    const data = [
      {country: 'Germany', score: 1},
      {country: 'Austria', score: 1},
      {country: 'Switzerland', score: 2},
      {country: 'Switzerland', score: 3}
    ];
    
    const result = data.reduce((a, {country, score}) => ({
      ...a,
      [country]: [...a[country] || [], {score}]
    }), {});
    
    console.log(result);
        2
  •  1
  •   Amila Senadheera    2 年前

    您可以使用 Array.prototype.reduce() 实现它。

    尝试如下:

    let data = [
      { country: "Germany", score: 1 },
      { country: "Austria", score: 1 },
      { country: "Switzerland", score: 2 },
      { country: "Switzerland", score: 3 },
    ];
    
    const output = data.reduce((prev, { country, score }) => {
      if (prev[country]) {
        prev[country].push({ score });
      } else {
        prev[country] = [{ score }];
      }
      return prev;
    }, {});
    
    console.log(output);
        3
  •  1
  •   bloodyKnuckles    2 年前

    你可以使用 reduce 函数,它获取一个数组,并根据对数组的每个元素所做的一些操作返回一个值。

    在您的情况下,此操作可能是将分数添加到另一个对象中已存在的关键点。

    这个 减少 函数接受一个带有两个参数的回调,一个是收集器,另一个是当前项。

    let data = [
      {country: 'Germany', score: 1},
      {country: 'Austria', score: 1},
      {country: 'Switzerland', score: 2},
      {country: 'Switzerland', score: 3}
    ];
    
    // since the reduce function returns a new object, we don't need to deep copy it.
    let dictionary = data.reduce((collector, x) => {
      // we first have to check if the key exists in the collector object.
      // to do so, we use the `in` operator, and negate it's output.
      if(!(x.country in collector)) {
        collector[x.country] = [];
      }
      
      // we, then, can push the current element's score into the appropriate array
      collector[x.country].push({score: x.score});
      
      // and we need to return the updated value. In our case, it's the collector.
      return collector;
    }, {} /** the second parameter of the function is the initial value of the collector */);
    
    console.log(dictionary)
        4
  •  0
  •   bloodyKnuckles    2 年前

    我喜欢的简洁和优雅 the accepted answer 然而,简洁和新技术使这个过程变得模糊。经过研究和询问,以下是我所了解的情况:

    result = data.reduce(
    

    reduce 循环遍历主题数组,并对每个元素执行一个函数,将上次迭代的结果传递给当前迭代,或第一次迭代的初始值。

    的第一个参数 减少 函数是用户定义的函数。该函数可以在其他地方定义并在此处命名,或者 anonymous function 可以就地定义。 Arrow function 在这种情况下,使用语法来表示匿名函数。

    首先,实例化参数变量以捕获输入并在函数体中使用。这里,实例化了两个参数变量:

        (
            a, // accumulator, returned value from the previous iteration
            {country, score} // value of currently iterated element of subject array, destructured
        ) => ({
    

    第一个参数是累加器对象,表示为变量 a 那么,在这种情况下,第二个是对象, {country, score} ,同时提供的电流元件 减少 -迭代阵列, 被分解为两个变量, country score ,对应于对象键。

    笔记:

    • 函数体完全由一个对象组成: => ({...}) 。此函数的所有操作都嵌入到对象表达式中。

    • 如果 arrow function consists of an expression that results in a single value ,在这种情况下是一个对象,不需要表达 return 例如 => { return {...} } .

    • 然而,由于表达式是一个对象,括号被包裹在对象周围, =>({...}) ,以便隐式返回对象,并防止大括号被解释为函数体分隔符。

    • 的有两种实现 spread 此对象表达式中的语法,两者或多或少都用于将两个对象或数组分别连接到单个对象或数组中。

    如前所述,函数体只是一个对象,继续将累积的对象“展开”到其键/值对的列表中,以便重新合并到累积的对象中:

        ) => ({
            ...a,
    

    在这里,Spread将累积对象的组件与新派生的对象组件有效地连接在一起,从而生成单个平面对象。

    接下来,从当前元素派生一个新的键/值对,并将其附加到累积的对象:

            [country]: // destructure, or interpolate, the variable, as key
    
            // array that accumulates the values of the above defined key
            [
                ...( // "spread" and assign the existing value of key (an array containing one or more objects)
                    a[country] || [] // get current value of key, if defined, but return an undefined value if not
                ),
                {score} // destructure variable and append object to array that is the value of the above key
            ]
      }), 
    

    新的对象键是动态的。换句话说,直到运行时才知道密钥的名称。变量的值 用于命名键,但由于在设置键时允许使用裸词,即未加引号的字符串,因此使用 country: 因为密钥不会将密钥设置为变量的值。为了将变量强制转换为其值,它被包装在一个文字数组中: [country]: 。返回的是一个数组,其中一个元素是变量的值。并且只允许字符串和符号作为对象键,因此 Array.prototype.toString 方法被自动调用以将数组转换为字符串。

    键/值对的值部分是一个数组。它收集一个对象列表。Spread也用于连接和展平之前收集的 分数 对象和 分数 当前迭代的,对应于键。OR运算符, || 用于首先确定累加器对象中现有密钥的存在,如果存在,则压平并合并现有分数。但是,如果密钥不存在,则提供一个空列表,有效地启动一个新列表。

    }), …并且隐含地 回来 下一次迭代的累积对象,或分配给 result 完成后。

    这个 减少 第一个参数,一个函数,现在已完全包含,依此类推 减少 函数第二个参数,用于第一次迭代:

      {} // an empty object
    );