【问题标题】:JS (ES6): Merge arrays based on id and concatenating sub arraysJS(ES6):基于 id 合并数组并连接子数组
【发布时间】:2018-09-13 22:02:24
【问题描述】:

我有两个数组,如下所示:

const persons = [
  {
    id: 1,
    name: 'Peter',
    job: 'Programmer'
  },
  {
    id: 2,
    name: 'Jeff',
    job: 'Architect'
  },
];

const salaries = [
  {
    id: 1,
    salary: 3000,
    departments: ['A', 'B'] 
  },
  {
    id: 1,
    salary: 4000,
    departments: ['A', 'C']
  },
  {
    id: 2,
    salary: 4000,
    departments: ['C', 'D']
  }
];

现在我需要以某种方式将这些数组合并为一个,以便每个 id 只存在一次。应该替换相同的键,除了它是一个数组,然后我希望它们添加/连接。所以想要的结果应该是这样的:

const result = [
  {
    id: 1,
    name: 'Peter',
    job: 'Programmer',
    salary: 4000,
    departments: ['A', 'B', 'C'] 
  },
  {
    id: 2,
    name: 'Jeff',
    job: 'Architect',
    salary: 4000,
    departments: ['C', 'D']
  }
];

我已经试过了:

// double id's, arrays get replaced
Object.assign({}, persons, salaries)

// loadsh: double id's, arrays get concatenated
_.mergeWith(persons, salaries, (objValue, srcValue) => {
    if (_.isArray(objValue)) {
        return objValue.concat(srcValue);
    }
});

// gives me a map but replaces arrays
new Map(salaries.map(x => [x.id, x])

有谁知道如何做到这一点?

【问题讨论】:

  • 我会给你一个提示,根据 id 对两个数组进行排序,然后尝试比较 em
  • 理解应该拿哪个薪水的逻辑是什么?最新的?薪水最高?
  • @MiguelAngel 最新的

标签: javascript arrays merge ecmascript-6 array-merge


【解决方案1】:

您可以使用map()、filter()、reduce()、Object.assign() 和Spread syntax 来获得所需的结果。

演示

const persons = [{
    id: 1,
    name: 'Peter',
    job: 'Programmer'
  }, {
    id: 2,
    name: 'Jeff',
    job: 'Architect'
  }],
  salaries = [{
    id: 1,
    salary: 3000,
    departments: ['A', 'B']
  }, {
    id: 1,
    salary: 4000,
    departments: ['A', 'C']
  }, {
    id: 2,
    salary: 4000,
    departments: ['C', 'D']
  }];


let output = persons.map(obj => {
  let filter = salaries.filter(v => v.id == obj.id);
  if (filter) {
    let departments = filter.reduce((r, v) => [...v.departments, ...r], []);
    Object.assign(obj, {
      salary: filter[filter.length - 1].salary,
      departments: departments.filter((item, pos) => departments.indexOf(item) == pos).sort()
    });
  }
  return obj;
});

console.log(output)

【讨论】:

【解决方案2】:

您可以concat 数组,而不是使用Array.reduce() 和Map 组合具有相同id 的所有项目。

要组合具有相同id 的对象,请从地图中获取对象。用Array.forEach() 迭代新的Object.entries()。检查现有值是否为数组,如果不赋值。如果是数组,则组合数组,并使用 Set 和数组 spread 使项目唯一。

要将 Map 转换回数组,您可以传播 Map.values() 迭代器。

const persons = [{"id":1,"name":"Peter","job":"Programmer"},{"id":2,"name":"Jeff","job":"Architect"}];
const salaries = [{"id":1,"salary":3000,"departments":["A","B"]},{"id":1,"salary":4000,"departments":["A","C"]},{"id":2,"salary":4000,"departments":["C","D"]}];

const result = [...persons.concat(salaries)
  .reduce((r, o) => {
    r.has(o.id) || r.set(o.id, {});
    
    const item = r.get(o.id);
    
    Object.entries(o).forEach(([k, v]) =>
      item[k] = Array.isArray(item[k]) ? 
        [...new Set([...item[k], ...v])] : v
    );
    
    return r;
  }, new Map()).values()];
  
console.log(result);

【讨论】:

    【解决方案3】:

    您可以使用 Map 并迭代所有属性并检查类型以向数组添加唯一值。

    var persons = [{ id: 1, name: 'Peter', job: 'Programmer' }, { id: 2, name: 'Jeff', job: 'Architect' }],
        salaries = [{ id: 1, salary: 3000, departments: ['A', 'B'] }, { id: 1, salary: 4000, departments: ['A', 'C'] }, { id: 2, salary: 4000, departments: ['C', 'D'] }],
        result = Array.from(
            salaries
                .reduce(
                    (m, o) => {
                        var t = m.get(o.id) || {};
                        Object.keys(o).forEach(k => {
                            if (Array.isArray(o[k])) {
                                t[k] = t[k] || [];
                                o[k].forEach(v => t[k].includes(v) || t[k].push(v));
                            } else if (t[k] !== o[k]) {
                                t[k] = o[k];
                            }
                        });
                        return m;
                    },
                    persons.reduce((m, o) => m.set(o.id, Object.assign({}, o)), new Map)
                )
                .values()
        );
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 2017-01-08
      • 2015-02-15
      • 1970-01-01
      • 2018-08-23
      • 1970-01-01
      相关资源
      最近更新 更多