js两个数组填充数据至一致 怎么写比较好?

假设有两个对象数组:

let arr1 = [
    {name:'a',val:11},
    {name:'b',val:21},
    {name:'c',val:31},
    {name:'e',val:51}
]

let arr2 = [
    {name:'a',val:12},
    {name:'b',val:22},
    {name:'d',val:42},
]
  1. 将两个数组的长度进行统一
  2. name没有重合的数据,生成同等的name,val设置为''
  3. name有重合的数据不管
  4. 顺序统一

最终的结果:

arr1 = [
    {name:'a',val:11},
    {name:'b',val:21},
    {name:'c',val:31},
    {name:'e',val:51}
    {name:'d',val:''},
]

arr2 = [
    {name:'a',val:12},
    {name:'b',val:22},
    {name:'c',val:''},
    {name:'e',val:''}
    {name:'d',val:42},
]
阅读 2.2k
3 个回答
var names = [...new Set(
    [...arr1.map(({ name }) => name),
    ...arr2.map(({ name }) => name)]
)]/*.sort()*/;
// 这里如果要以 a 为先,b 追加,就不需要排序
// 加 sort() 对 name 进行排序,可以保证 name 按字母序

arr1 = names.map(name => ({ name, val: arr1.find(it => it.name === name)?.val ?? "" }));
arr2 = names.map(name => ({ name, val: arr2.find(it => it.name === name)?.val ?? "" }));

console.log(arr1);
console.log(arr2);

如果想保持原有的对象引用,map 那里改一下就好了

arr1 = names.map(name => arr1.find(it => it.name === name) ?? { name, val: "" });
arr2 = names.map(name => arr2.find(it => it.name === name) ?? { name, val: "" });

如果想少循环一次 names,可以用 reduce

[arr1, arr2] = names.reduce((all, name) => {
    all[0].push(arr1.find(it => it.name === name) ?? { name, val: "" });
    all[1].push(arr2.find(it => it.name === name) ?? { name, val: "" });
    return all;
}, [[], []]);

如果 arr1 和 arr2 数据量比较大,find 会比较耗时,可以提前生成查找表:

const arr1Map = Object.fromEntries(arr1.map(it => [it.name, it]));

// arr1.find(it => it.name === name) ?? { name, val: "" }
// ⇓
arr1Map[name] ?? { name, val: "'" }
let arr1NameList = arr1.map(v => v.name)
let arr2NameList = arr2.map(v => v.name)
let allNameList = [...new Set([...arr1NameList, ...arr2NameList])]
let list = allNameList.reduce((s, v) => {
  !arr1NameList.includes(v) && s[0].push({name: v, val: ''})
  !arr2NameList.includes(v) && s[1].push({name: v, val: ''})
  return s
}, [arr1, arr2]).map(it => it.sort((s, v) => allNameList.indexOf(s.name) - allNameList.indexOf(v.name)))
arr1 = list[0]
arr2 = list[1]
console.log(arr1,arr2)
var totalKey = [...new Set(
    [...arr1.map(({ name }) => name),
    ...arr2.map(({ name }) => name)]
)] // * 此处生成name代码来自 边城 大佬(#^.^#)
function genera(arr) {
  let n = 0;
  let filterArr = [];
  while (n < totalKey.length) {
    let idx = arr.findIndex((item) => item.name == totalKey[n]);
    if (idx != -1) {
      filterArr.push(...arr.splice(idx, 1));
    } else {
      filterArr.push({ name: totalKey[n], val: "" });
    }
    n++;
  }
  return filterArr
}
console.log(genera(arr1));
console.log(genera(arr2));
推荐问题