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

如何基于键名合并2个数组,并基于合并值排序?

  •  2
  • sefirosu  · 技术社区  · 5 年前

    假设我有两张单子

    const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
    const listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
    

    问题是,如何将两个列表合并到一个堆栈中,使同一个项目以数字递增并按数量排序?我的意思是最终的结果应该是->

    const listMerged = [{"apple":115}, {"banana": 50} , {"peach": 30}, {"kiwi": 13}, {"pearl": 10}, {"cherry": 5}, {"mango": 5}]
    

    我知道会是这样的:

    sortListDesc(list) {
    
        return obj.sort(function (l1,l2) {
          return l2< l1 ? -1
               : l2 >l1 ? 1
               : 0
        })
      }
    

    但不知道如何确切地堆叠数字,比按数量编号排序。

    3 回复  |  直到 5 年前
        1
  •  2
  •   adiga    5 年前

    你可以使用 reduce sort Object.values 这样地:

    const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
    , listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
    
    let merged = Object.values(listA.concat(listB).reduce((acc, a) => {
      const [k, v] = Object.entries(a)[0];
      (acc[k] = acc[k] || {[k]: 0})[k] += v;
      return acc;
    }, {}));
    
    merged.sort((a, b) => Object.values(b)[0] - Object.values(a)[0]);
    console.log(merged);

    或者,

    使用 减少 创建一个以所有水果为键,单个和为值的对象。然后使用 Object.entries , 分类 map 这样地:

    const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
    , listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
    
    let merged2 = listA.concat(listB).reduce((acc, a) => {
      const [k, v] = Object.entries(a)[0];
      acc[k] = (acc[k] || 0) + v;
      return acc;
    }, {});
    
    const final = Object.entries(merged2)
      .sort(([, v1], [, v2]) => v2 - v1)
      .map(([k, v]) => ({[k]: v}))
    
    console.log(final);
        2
  •  1
  •   brk    5 年前

    您可以使用 forEach 并使用检查第一个列表中是否存在相同的元素 findIndex . 如果元素不存在(-1),则将元素推到第一个列表中。如果存在,则使用索引获取该对象,然后在 for..in

    const listA = [{
      "apple": 100
    }, {
      "banana": 50
    }, {
      "pearl": 10
    }, {
      "cherry": 5
    }, {
      "kiwi": 3
    }]
    const listB = [{
      "peach": 30
    }, {
      "apple": 15
    }, {
      "kiwi": 10
    }, {
      "mango": 5
    }]
    let newArr = listB.forEach((item) => {
      let ifElemPresentInListA = listA.findIndex((elem) => {
        return Object.keys(elem)[0] === Object.keys(item)[0]
    
      })
    
      if (ifElemPresentInListA === -1) {
        listA.push(item)
      } else {
        for (let keys in listA[ifElemPresentInListA]) {
          listA[ifElemPresentInListA][keys] += Object.values(item)[0]
        }
      }
    
    })
    
    console.log(listA)
        3
  •  1
  •   Ivan Satsiuk    5 年前

    我想我的代码比 BRK

    const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
    const listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
    
    const both = Object.assign({}, ... listA, ... listB); // concatenate both lists and convert them to an object
    const lA = Object.assign({}, ...listA); // convert listA to an object
    const lB = Object.assign({}, ...listB);
    
    var result = Object.keys(both).map( (a) => { // mapping sums the values and yields an array
      var sum = {};
      sum [a] =(lA[a] ? lA[a] : 0) + (lB[a] ? lB[a] : 0);
      return sum;
    });
    // sorting in desc order (hence b - a ) based on values (hence b[Object.keys(b)]) rather than keys
    result.sort((a,b) => b[Object.keys(b)] - a[Object.keys(a)] ); 
    

    复杂性是由于您将值存储为数组这一事实造成的。 我认为这不是获得它的最佳方法,因为数组可以有多个元素具有相同的键。例如,你可以得到这样的结果: const listA = [{"apple":100},...,{"apple":10}] 这是有效的,但会造成问题。 我建议您考虑将其用作对象,例如: const listA = {{'apple': 100}, {'banana':50}} 这将大大简化代码,并确保没有重复的代码

    希望有帮助!