js数据合并问题

根据key合并ab的数据得到result,代码怎么写性能好?要考虑实际数据比这个多几层嵌套。

const a = [
  {
    key: "id",
    num: "111",
  },
  {
    key: "age",
    num: "222",
  }
];

const b = [
  {
    key: "age",
    initVal: "23"
  },
  {
    key: "id",
    initVal: "001"
  }
];

const result = [
  {
    key: "id",
    initVal: "001",
    num: "111",
  },
  {
    key: "age",
    initVal: "23",
    num: "222",
  }
];
阅读 4.2k
5 个回答

如果你允许修改a或者b中的值,那么可以这样

// 新建对象放入a的数据
const data = {};

// 用key值做属性加速查找
a.forEach(item => {
    data[item.key] = item;
})

// 将a的数据合并到b
b.forEach(item => {
    Object.assign(item, data[item.key]);
})

// 得到结果
console.log(b);

如果不允许,那么

// result数组用于存放结果
const result = [];

// 同上
const data = {};
a.forEach(item => {
    data[item.key] = item;
})

// 遍历b,合并数据到新对象后插入result中
b.forEach(item => {
    result.push(Object.assign({}, data[item.key], item));
})

console.log(result);

如果多个数组之间的对象顺序是严格对应的,可以用 Lodash 的 _.merge,如果不是,就这样:

/**
 * @param keyName 用于对应多个数组中对象的 key 字段名称
 * @param first 第一个数据
 * @param args 剩下的一个或多个数组
 */
function merge(keyName, first, ...args) {
    // 这里假设数组内就是普通对象,如果是多层次的对象,理论上来说应该用深拷贝
    // 不过具体用浅拷贝还是深拷贝,要看实际需求
    const result = first.map(m => ({ ...m }));

    // 根据 key 建立一个映射表,方面后面快速检索
    const map = result.reduce((agg, m) => {
        agg[m[keyName]] = m;
        return agg
    }, {});
    
    // 每个 next 就是一个数组
    for (let next of args) {
        // 遍历数组中的每一个对象 m
        for (let m of next) {
            // 根据 key 找到已经存在的模型
            let model = map[m[keyName]];
            if (model) {
                // 如果找到了,就直接将 m 合并到模型中去
                Object.assign(model, m);
            } else {
                // 没找到就按新 key 建立新的模型,这里和上面一样,理论上来说应该用深拷贝
                map[m[keyName]] = { ...m };
            } 
        }
    }
    return result;
}

oneliner 又来凑热闹... 供参考

const merge = (a,b) =>[...a.concat(b).reduce((m, x) => m.set(x.key, Object.assign(m.get(x.key) || {}, x)), new Map()).values()]
const a = [ { key: "id", num: "111", }, { key: "age", num: "222", } ]
const b = [ { key: "age", initVal: "23" }, { key: "id", initVal: "001" } ]

console.log(merge(a,b))
新手上路,请多包涵
function selectKey(key) {
    // 使用es6数组实例的find方法
    const result_a = a.find(elem => elem.key == key)
    const result_b = b.find(elem => elem.key == key)
    return { ...result_a, ...result_b }
}

const result = a.map(elem => selectKey(elem.key))

只提供个思路

  • 如果两个数组按key对应,可以先做排序(已经是相同的顺序则不需要),然后直接过一遍merge
  • 如果不是,则按照第一个回答,用一个中间对象做映射,然后返回merge后的b对象
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题