删除“复杂”的重复项

Posted

技术标签:

【中文标题】删除“复杂”的重复项【英文标题】:Removing 'complicated' duplicates 【发布时间】:2018-07-10 19:11:15 【问题描述】:

Test File

有时,我的电子邮件列表中包含同一个人的重复地址。例如,Jane 的地址既是“jane.doe@email.com”又是“doe.jane@email”。她的变体包括替换“。”用“-”或“_”。目前,我的重复脚本(由@Jordan Running 和 Ed Nelson 非常友好地升级)负责“严格”重复,但无法检测到“doe.jane@email.com”是“jane”的“复杂”重复.doe@email.com”。有没有办法删除甚至 这些 重复项,这样我就不会通过电子邮件发送多个 Jane 的地址?他们都指向同一个收件箱,所以我只需要包括她的一个地址。

这是我当前的代码:

function removeDuplicates() 
  const startTime = new Date();
  const newData = [];
  const sheet = SpreadsheetApp.getActiveSheet();
  const data = sheet.getDataRange().getValues();
  const numRows = data.length;
  const seen = ;

  for (var i = 0, row, key; i < numRows && (row = data[i]); i++) 
    key = JSON.stringify(row);
    if (key in seen) 
      continue;
    
    seen[key] = true;
    newData.push(row);
  ;

  sheet.clearContents();
  sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData);

  // Show summary
  const secs = (new Date() - startTime) / 1000;
  SpreadsheetApp.getActiveSpreadsheet().toast(
    Utilities.formatString('Processed %d rows in %.2f seconds (%.1f rows/sec); %d deleted',
                           numRows, secs, numRows / secs, numRows - newData.length),
    'Remove duplicates', -1);

【问题讨论】:

建立这些关系对于每个用户来说都是非常具体的,而且几乎不可能,请考虑jane.doe@gmail.comjdoe@gmail.com。我建议在收集电子邮件时使用主要/辅助电子邮件。 是的,同意 Phillip Thomas 的观点——我对此有一些经验,很难确定地消除潜在的重复(在 Phillip Thomas 中,例如 jdoe.gmail.com jane doe 或者它是 joe是吗?)最后我想出的最好办法是运行一个功能,提醒潜在的重复并让人类做出最终决定。 感谢@PhillipThomas,但有没有办法只捕获 jane.doe@email.com 和 doe.jane@email.com 变体? 不是真的:关键是你无法知道jane.doe@email.comdoe.jane@email.com 是否真的是同一个人。 @msanford,感谢您的来信。我假设在我的工作表中 99% 的情况下,这些地址直接发送到同一个收件箱。 【参考方案1】:

Sample File

模糊匹配测试

注意事项:

在没有@email.com 部分的情况下使用,它会扭曲结果 使用自定义函数:=removeDuplicatesFuzzy(B2:B12,0.66) 0.66 是模糊匹配的百分比。 结果的右列(D 列)显示找到的匹配项的准确度 > 0.66。破折号- 是找不到匹配项(“唯一”值)

背景

你可以试试这个库: https://github.com/Glench/fuzzyset.js

要安装它,请复制代码from here。

用法很简单:

function similar_test(string1, string2)

  string1 = string1 || 'jane.doe@email.com';
  string2 = string2 || 'doe.jane@email.com'
  a = FuzzySet();
  a.add(string1);
  var result = a.get(string2);
  
  Logger.log(result);  // [[0.6666666666666667, jane.doe@email.com]]
  
  return result[0][0]; // 0.6666666666666667

这里还有更多信息:https://glench.github.io/fuzzyset.js/

注意事项:

请谷歌更多信息,寻找javascript fuzzy string match。这是相关的Q:Javascript fuzzy search that makes sense。注意:该解决方案应该适用于 Google 表格(无 ECMA-6) 这个算法不像人类那样聪明,它按字符测试字符串。如果您有两个类似的字符串,例如 don.jeans@email.com,它将与 doe.jane@email.com 有 84% 的相似性,但人类检测到它完全是另一个人。

【讨论】:

谢谢,@Max。我不确定我是否理解。我从链接中复制了代码,然后将其粘贴到我的测试表中,但我收到了以前从未见过的错误。我的测试表在这里:docs.google.com/spreadsheets/d/… 嗨,@ed-dev,感谢您提供测试文件。我已经做了一些测试,但我得到的最好结果仍然离你的目标还很远。如果对您有帮助,请尝试我的示例。到目前为止,我找不到更好的解决方案。但我喜欢你的问题,并想为此提出赏金,看看更好的方法。 谢谢你,@Max Makhrov。给定权限,我无法使用您的示例文件查看脚本代码。 (仅供参考,您答案中指向“测试模糊匹配”的链接与我帖子中的“测试表 2”链接不同,如果您设置赏金,这可能会导致混淆。) 首先,我认为只要有 john.doe@email.com,就可以删除不太复杂的重复项,例如 john-doe@email.com。 嗨@Max。不知道你对这个问题有没有更多的想法。【参考方案2】:

搜索我的 Google 表格插件 Flookup。它应该做你想做的。

对于您的情况,您可以使用此功能:

ULIST(colArray, [threshold])

参数详情为:

    colArray:要返回唯一值的列。 threshold:不唯一的 colArray 值之间的最小相似度百分比。

或者您可以简单地使用附加菜单中的突出显示重复项删除重复项。 关键功能是您可以通过更改百分比相似度来调整严格程度。

奖励:它将轻松捕获像jane.doe@email.com / doe.jane@email.com 这样的交换

您可以通过official website了解更多信息。

【讨论】:

以上是关于删除“复杂”的重复项的主要内容,如果未能解决你的问题,请参考以下文章

从Dart列表中删除重复项的2种方法

python如何删除list里重复的元素

如何删除重复条目?

使用 C# 在复杂的 JSON 数组中查找和打印重复项

从列表中删除重复项?

删除没有主键的重复项