【问题标题】:Return similar values ​from multiple array of objects in Javascript从 Javascript 中的多个对象数组中返回相似的值
【发布时间】:2021-09-27 01:18:13
【问题描述】:

伙计们,我做了一个简单的例子来说明我的问题。我有 3 个对象数组,datasOnedatasTwodatasThree,我想要的是只返回一个包含 3 个数组中的对象的新数组。例如,如果 3 个数组中只有 Gustavo,则返回他。但是有一个细节是,如果datasThree 是一个空数组,那么它只会带来来自datasOnedatasTwo 的共同数据,并且如果只有datasTwo 有数据并且其他两个数组有空, 那么它将只返回来自datasTwo 的数据。换句话说,它只从有数据的数组中返回相似的数据。我设法做到了这个算法,它按照我想要的方式工作,但我想知道另一种方法来使它不那么冗长,也许更简单,并且在我添加更多数组进行比较的情况下也可以工作,例如dataFour。我感谢任何可以帮助我的人。

我的代码如下:

let datasOne = [
  { id: 1, name: 'Gustavo' },
  { id: 2, name: 'Ana' },
  { id: 3, name: 'Luiz' },
  { id: 8, name: 'Alice' }
]

let datasTwo = [
  { id: 1, name: 'Gustavo' },
  { id: 3, name: 'Luiz' },
  { id: 8, name: 'Alice' }
]

let datasThree = [
  { id: 1, name: 'Gustavo' },
  { id: 3, name: 'Luiz' },
  { id: 2, name: 'Ana' },
  { id: 5, name: 'Kelly' },
  { id: 4, name: 'David' }
]

let filtered

if (datasOne.length > 0 && datasTwo.length > 0 && datasThree.length > 0) {
  filtered = datasOne.filter(firstData => {
    let f1 = datasThree.filter(
      secondData => firstData.id === secondData.id
    ).length
    let f2 = datasTwo.filter(
      secondData => firstData.id === secondData.id
    ).length
    if (f1 && f2) {
      return true
    }
  })
} else if (datasOne.length > 0 && datasTwo.length > 0) {
  filtered = datasOne.filter(firstData => {
    return datasTwo.filter(secondData => firstData.id === secondData.id).length
  })
} else if (datasOne.length > 0 && datasThree.length > 0) {
  filtered = datasOne.filter(firstData => {
    return datasThree.filter(secondData => firstData.id === secondData.id)
      .length
  })
} else if (datasTwo.length > 0 && datasThree.length > 0) {
  filtered = datasTwo.filter(firstData => {
    return datasThree.filter(secondData => firstData.id === secondData.id)
      .length
  })
} else if (datasThree.length > 0) {
  filtered = datasThree
} else if (datasTwo.length > 0) {
  filtered = datasTwo
} else if (datasOne.length) {
  filtered = datasOne
}

console.log(filtered)

【问题讨论】:

  • 一个数组是否只有一次唯一的对象?如果一个数组有两次{ id: 1, name: 'Gustavo' } 是可能的吗?
  • 是否可以有 2 个id 给不同的人?
  • 没有。每个人的 ID 都是唯一的。在我制作的算法中,'filtered' 的返回将是 [ { "id": 1, "name": "Gustavo"}, { "id": 3, "name": "Luiz"}] 因为这些对象在 3 个数组中找到

标签: javascript arrays javascript-objects


【解决方案1】:

1)你可以先filterarrs中不为空的数组。

const arrs = [datasOne, datasTwo, datasThree].filter((a) => a.length);

2) 使用flat() 展平arrs 数组。

arrs.flat()

3) 循环扁平化数组并使用Map统计所有对象的出现次数

const map = new Map();
for (let o of arrs.flat()) {
  map.has(o.id)
    ? (map.get(o.id).count += 1)
    : map.set(o.id, { ...o, count: 1 });
}

4) 循环map 并仅在等于arrs.length 时收集结果

if (count === arrs.length) result.push(rest);

let datasOne = [
  { id: 1, name: "Gustavo" },
  { id: 2, name: "Ana" },
  { id: 3, name: "Luiz" },
  { id: 8, name: "Alice" },
];

let datasTwo = [
  { id: 1, name: "Gustavo" },
  { id: 3, name: "Luiz" },
  { id: 8, name: "Alice" },
];

let datasThree = [
  { id: 1, name: "Gustavo" },
  { id: 3, name: "Luiz" },
  { id: 2, name: "Ana" },
  { id: 5, name: "Kelly" },
  { id: 4, name: "David" },
];

const arrs = [datasOne, datasTwo, datasThree].filter((a) => a.length);

const map = new Map();
for (let o of arrs.flat()) {
  map.has(o.id)
    ? (map.get(o.id).count += 1)
    : map.set(o.id, { ...o, count: 1 });
}

const result = [];
for (let [, obj] of map) {
  const { count, ...rest } = obj;
  if (count === arrs.length) result.push(rest);
}

console.log(result);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 完美。很聪明!谢谢老哥回答
【解决方案2】:

不是 100% 确定它涵盖了所有边缘情况,但这可能会让您走上正确的道路:

function filterArrays(...args) {
  const arraysWithData = args.filter((array) => array.length > 0);
  const [firstArray, ...otherArrays] = arraysWithData;

  return firstArray.filter((item) => {
    for (const array of otherArrays) {
      if (!array.some((itemTwo) => itemTwo.id === item.id)) {
        return false;
      }
    }
    return true;
  });
}

用法:

const filtered = filterArrays(datasOne, datasTwo, datasThree);
console.log(filtered)

我相信代码相当可读,但如果有不清楚的地方,我很乐意澄清。

【讨论】:

  • 非常好的朋友。另一个聪明的选择。谢谢!
【解决方案3】:
function merge(arr){
  arr = arr.filter(item=>item.length>0)
  const map = {};
  arr.forEach(item=>{
    item.forEach(obj=>{
      if(!map[obj.id]){
        map[obj.id]=[0,obj];
      }
      map[obj.id][0]++;
    })
  })
  const len = arr.length;
  const ret = [];
  Object.keys(map).forEach(item=>{
    if(map[item][0]===len){
      ret.push(map[item][1])
    }
  })
  return ret;
}
merge([datasOne,datasTwo,datasThree])

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 2017-07-17
相关资源
最近更新 更多