【问题标题】:Remove duplicate entries from array but keep the most complete entries从数组中删除重复条目,但保留最完整的条目
【发布时间】:2021-01-29 16:12:54
【问题描述】:

我有一个多维数组,其值如下:

let unfilteredArray = [
  ["1234", "no email entered", "other value", null, 7, "another value"],
  ["3333", "b@example.com", "another value", 2, 10, "something else"],
  ["1234", "a@example.com", "random value", 2, null, "something else"],
  ["4444", "c@example.com", "another value", 29, 3, "xxx"],
  ["5555", "abcd", "another value", 3, 41, "yyy"],
  ["1234", "another random text", "another value", 4, 8, "zzz"],
  ["5555", "efgh", "another value", null, 0, null]
];

我想提取唯一的用户 ID,但在列索引 1 中保留带有电子邮件的条目。如果给定的用户 ID 没有电子邮件,则使用给定用户 ID 的最后一行。所选行的所有其他列应保留在输出中。

上述值的结果应如下所示:

let unfilteredArray = [
  ["1234", "a@example.com", "random value", 2, null, "something else"],
  ["3333", "b@example.com", "another value", 2, 10, "something else"],
  ["4444", "c@example.com", "another value", 29, 3, "xxx"],
  ["5555", "efgh", "another value", null, 0, null] // no email for User ID 5555 => last 5555 row used
];

到目前为止,我有一个删除重复的脚本:

// index = index of the column with User ID
function removeDuplicates(array, index) {
  // Gets only the first entry - the rest are removed
  let filteredArray = [];
  for (let i = 1; i < array.length; i++) {
    let isDuplicate = false;
    for (let j = i-1; j >= 0; j--) {
      if (array[i][index] == array[j][index]) {
        isDuplicate = true;
        break;
      }
    }
    if (!isDuplicate) {
      filteredArray.push(array[i]);
    }
  }
  return filteredArray;
}

如何确保返回带有电子邮件的行?

【问题讨论】:

  • 请将表格转换为数组。
  • 你可以按用户ID对数组进行分组,然后.reduce每组到一个记录吗?如果您在示例数据中包含一个,我会试一试。
  • 某些列可以包含空值。也许正因为如此,建议的解决方案不起作用?我更新了示例以尽可能接近真实案例。谢谢!

标签: javascript arrays sorting unique


【解决方案1】:

将数组简化为 Map,并在 Map 中仅包含 ID (key) 但 Map 上不存在的行,或者其值为电子邮件的行。使用数组扩展将 Map 的 .values() 转换回数组,或 Array.from()

注意:validateEmail(email) 函数取自 answer

function validateEmail(email) {
  const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  return re.test(String(email).toLowerCase());
}

function removeDuplicates(array) {
  return Array.from(
    array.reduce((acc, row) => {
      const [key, value] = row;
      
      if(!acc.has(key) || validateEmail(value)) {
        acc.set(key, row);
      }
     
      return acc;
    }, new Map()).values()
  )
}

const unfilteredArray = [["1234","no email entered","other value",null,7,"another value"],["3333","b@example.com","another value",2,10,"something else"],["1234","a@example.com","random value",2,null,"something else"],["4444","c@example.com","another value",29,3,"xxx"],["5555","abcd","another value",3,41,"yyy"],["1234","another random text","another value",4,8,"zzz"],["5555","efgh","another value",null,0,null]];

const result = removeDuplicates(unfilteredArray);

console.log(result);

【讨论】:

  • 非常感谢您的回答!我尝试了您的解决方案,但它不适用于真实案例。我在应该保留的多维数组中有更多列。您能否更新解决方案以保留这些解决方案?我更新了这个问题,所以它与真实案例是准确的。
  • 无论数组的长度如何,只要id 是连续的第一项,并且电子邮件是第二项,此解决方案都有效。我已使用您的新数据更新了示例,但并未更改解决方案本身。
【解决方案2】:

我在 Stackoverflow 上结合了一些答案,得到了这段代码。我将您的数组更改为对象。如果不重要,这里是我的结果代码

var unfilteredArray = [
  {id:1234, text: "no email entered"},
  {id:3333, text: "b@example.com"},
  {id:1234, text: "a@example.com"},
  {id:4444, text: "c@example.com"},
  {id:5555, text: "abcd"},
  {id:1234, text: "another random text"},
  {id:5555,text: "efgh"}
];

function isValidEmail(email) {
    const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  return re.test(String(email).toLowerCase());
}

var arr2 = unfilteredArray.reduce( (a,b) => {
    var i = a.findIndex( x => x.id === b.id);
    return i === -1 ? a.push({ id : b.id, text : b.text }) : a[i].text = 
    this.isValidEmail(a[i].text) ? a[i].text: b.text, a;
}, []);

console.log(arr2)

*验证邮件功能链接 => here

【讨论】:

  • 非常感谢您的回答!我把它作为一个数组,所以我将你的解决方案更新为我在真实案例中尝试过的数组。不幸的是,它不起作用。我在应该保留的多维数组中有更多列。您能否更新解决方案以保留这些解决方案?也许问题在于某些值为空的值?我更新了这个问题,所以它与真实案例是准确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-08
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2017-12-01
相关资源
最近更新 更多