【问题标题】:Join array elements if another array have same elements如果另一个数组具有相同的元素,则连接数组元素
【发布时间】:2018-05-08 06:18:16
【问题描述】:

我有两个数组

var arrayA = ["a", "a", "b", "b", "a", "c"];
var arrayB = [10, 20, 3, 2, 20, 5];

如您所见,arrayA[0], arrayA[1], arrayA[4] 具有相同的元素(arrayA[2], arrayA[3] 也相同)。

所以基于上面的例子,我想总结一下arrayB[0], arrayB[1], arrayB[4],还有arrayB[2], arrayB[3]

期望输出

arrayA = ["a", "b", "c"];
arrayB = [50, 5, 5];

如果arrayA 具有相同的基于arrayA 索引的元素,是否可以对arrayB 元素求和?是否有 Lodash/Underscore 函数可以做到这一点?

【问题讨论】:

  • 你有没有尝试过?
  • @Pratansyah 虽然我非常感谢您的努力,但这并不是重复的。 OP 希望对第二个数组中的值求和并使其唯一。

标签: javascript arrays underscore.js lodash


【解决方案1】:

使用Array#reduce 方法。

var arrayA = ["a", "a", "b", "b", "a", "c"];
var arrayB = [10, 20, 3, 2, 20, 5];

// reference to keep the index
var ref = {},
  // array for keeping first result
  res1 = [];


var res2 = arrayA
  // iterate over the first array
  .reduce(function(arr, v, i) {
    // check index presenet in the refernece object
    if (!(v in ref)) {
      // if not then define the index and insert  0 in the array(defining the new index)
      arr[ref[v] = arr.length] = 0;
      // push value into the array( for unique value )
      res1.push(v);
    }
    // update the element at the index
    arr[ref[v]] += arrayB[i];
    // return the array reference
    return arr;
    // initialize initial value as an empty array to keep result
  }, [])

console.log(res1, res2);

【讨论】:

  • arrayA 输出呢?
【解决方案2】:

您可以将两个数组reduce 转换为 ES6 Map,然后将 spread keys 用于 arrayA,values 用于 arrayB:

const arrayA = ["a", "a", "b", "b", "a", "c"];
const arrayB = [10, 20, 3, 2, 20, 5];

const map = arrayA.reduce((m, c, i) => m.set(c, (m.get(c) || 0) + arrayB[i]), new Map());

const arrA = [...map.keys()];
const arrB = [...map.values()];

console.log(arrA);

console.log(arrB);

【讨论】:

    【解决方案3】:

    这是一个使用 lodash 的解决方案:

    [arrayA, arrayB] = _(arrayA)
        .zip(arrayB)
        .groupBy(0)
        .mapValues( grp => _.sumBy(grp,1))
        .thru(obj => [_.keys(obj), _.values(obj)])
        .value();
    

    zip 会将arrayA 中的每个元素与arrayB 中的相应元素相关联,例如[ ['a', 10], ['a', 20], ...]

    然后我们 groupBy 位置 0 的值给出一个对象,如下所示:

    {
       a: ['a', 10], ['a', 20], ['a', 20'],
       b: ['b', 3] ...,
       c: ...
    }
    

    然后将每个键的值映射到位置 1 中的值的总和,然后最终返回不同数组中的键和值。

    【讨论】:

      【解决方案4】:

      首先填充dict,然后用键和值填充de数组

      let arrayA = ["a", "a", "b", "b", "a", "c"];
      let arrayB = [10, 20, 3, 2, 20, 5];
      
      let result = {};
      
      for (let i=0; i < arrayA.length; i++ ){
          let valueB = 0;
          if (arrayB.length > i) {
              valueB = arrayB[i];
          }
      
          if (result.hasOwnProperty(arrayA[i])) {
            result[arrayA[i]] += valueB;
          }
          else {
            result[arrayA[i]] = valueB;
          }
      }
      
      let resultA = [];
      let resultB = [];
      for (let k in result) {
          resultA.push(k);
          resultB.push(result[k]);
      }
      console.log(resultA);
      console.log(resultB);
      

      【讨论】:

        【解决方案5】:

        您可以使用对象作为索引并维护值。

        var arrayA = ["a", "a", "b", "b", "a", "c"],
            arrayB = [10, 20, 3, 2, 20, 5],
            indices = Object.create(null),
            groupedA = [],
            groupedB = [];
            
        arrayA.forEach(function (a, i) {
            if (!(a in indices)) {
                groupedA.push(a);
                indices[a] = groupedB.push(0) - 1;
            }
            groupedB[indices[a]] += arrayB[i];
        });
        
        console.log(groupedA);
        console.log(groupedB);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        改变原始数组的版本。

        var arrayA = ["a", "a", "b", "b", "a", "c"],
            arrayB = [10, 20, 3, 2, 20, 5],
            indices = Object.create(null),
            i = 0;
        
        while (i < arrayA.length) {
            if (!(arrayA[i] in indices)) {
                indices[arrayA[i]] = i++;
                continue;
            }
            arrayB[indices[arrayA[i]]] += arrayB.splice(i, 1)[0];
            arrayA.splice(i, 1);
        }
        
        console.log(arrayA);
        console.log(arrayB);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        【讨论】:

        • 哇...groupedB.push(0) - 1;,这真是个好方法:)
        • push 返回推入后的数组长度。
        • 我对@9​​87654327@这个说法有点困惑,还要解释一下吗?
        • @EngkusKusnadi,它在groupedB 的末尾压入零值,并且因为push 返回数组的新长度,所以你得到最后一个插入项的索引,减量为- 1。结果是哈希表indices 中的索引处的值为零。在下一行中,索引用于更新哈希表索引处相同项目的总和。
        【解决方案6】:
        let _ = require('underscore');
        
        var arrayA = ["a", "a", "b", "b", "a", "c"];
        var arrayB = [10, 20, 3, 2, 20, 5];
        
        let res = {};
        _.each(arrayA, (item, key) => {
        
          if (! res[item]) {
            res[item] = arrayB[key];
          } else {
            res[item] = res[item] + arrayB[key];
          }
        
        });
        
        arrayA = [];
        arrayB = [];
        
        _.each(res,(value,key) => {
          arrayA.push(key);
          arrayB.push(value);
        });
        
        console.log(arrayA);
        console.log(arrayB);
        

        【讨论】:

          【解决方案7】:

          您可以计算 arrayB 中与 arrayA 中的每个元素对应的所有元素的总和,将这些总和存储在一个对象中,然后使用 Object.values 获取总和数组。

          var arrayA = ["a", "a", "b", "b", "a", "c"];
          var arrayB = [10, 20, 3, 2, 20, 5];
          
          var sum = {};
          
          arrayA.forEach((l, index) => {
              sum[l] = (sum[l] || 0) + arrayB[index];
          });
          
          var res = Object.values(sum);
          
          console.log(res);

          使用 array.prototype.reduce 可以做得更短:

          var arrayA = ["a", "a", "b", "b", "a", "c"];
          var arrayB = [10, 20, 3, 2, 20, 5];
          
          var res = Object.values(arrayA.reduce((m, l, index) => {
              m[l] = (m[l] || 0) + arrayB[index];
              return m;
          }, {}));
          
          console.log(res);

          【讨论】:

            【解决方案8】:

            使用中间“结果”对象:

            var arrayA = ["a", "a", "b", "b", "a", "c"];
            var arrayB = [10, 20, 3, 2, 20, 5];
            var result = {};
            
            for (var i = 0, max = arrayA.length; i < max; i++) {
                if (!result[arrayA[i]]) {
                    result[arrayA[i]] = 0;
                }
            
                result[arrayA[i]] += arrayB[i];
            }
            
            var keys = Object.keys(result);
            
            arrayA = [];
            arrayB = [];
            for (var i = 0, max = keys.length; i < max; i++) {
                arrayA.push(keys[i]);
                arrayB.push(result[keys[i]]);
            }
            

            【讨论】:

              猜你喜欢
              • 2017-05-14
              • 2023-03-07
              • 1970-01-01
              • 2021-01-10
              • 1970-01-01
              • 2014-01-03
              • 1970-01-01
              • 2021-07-19
              • 2022-07-06
              相关资源
              最近更新 更多