【问题标题】:Fuzzy matching in Google SheetsGoogle 表格中的模糊匹配
【发布时间】:2022-11-26 12:14:01
【问题描述】:

尝试将 Google 表格中的两列与 C 列中的此公式进行比较:

=if(A1=B1,"","Mismatch")

工作正常,但我收到很多误报:

A. B C
MARY JO Mary Jo
JAY, TIM TIM JAY Mismatch
Sam Ron Sam Ron Mismatch
Jack *Ma Jack MA Mismatch

任何想法如何工作?

【问题讨论】:

  • 你是说假阴性吗?您是否希望所有这些都匹配?还是您期望只有第二行不匹配?请包括一个更具描述性的列表,该列表将显示比较 2 列的预期结果。

标签: regex if-statement google-apps-script google-sheets google-sheets-formula


【解决方案1】:

这使用基于分数的方法来确定匹配。您可以根据该分数确定什么是/不匹配:

Score Formula = getMatchScore(A1,B1)
Match Formula = if(C1<.7,"mismatch",)
function getMatchScore(strA, strB, ignoreCase=true) {
  strA = String(strA);
  strB = String(strB)
  const toLowerCase = ignoreCase ? str => str.toLowerCase() : str => str;
  const splitWords = str => str.split(//);
  let [maxLenStr, minLenStr] = strA.length > strB.length ? [strA, strB] : [strB, strA]; 
  
  maxLenStr = toLowerCase(maxLenStr);
  minLenStr = toLowerCase(minLenStr);

  const maxLength = maxLenStr.length;
  const minLength = minLenStr.length;
  const lenScore = minLength / maxLength;

  const orderScore = Array.from(maxLenStr).reduce(
    (oldItem, nItem, index) => nItem === minLenStr[index] ? oldItem + 1 : oldItem, 0
  ) / maxLength;

  const maxKeyWords = splitWords(maxLenStr);
  const minKeyWords = splitWords(minLenStr);

  const keywordScore = minKeyWords.reduce(({ score, searchWord }, nItem) => {
    const newSearchWord = searchWord?.replace(new RegExp(nItem, ignoreCase ? 'i' : ''), '');
    score += searchWord.length != newSearchWord.length ? 1: 0;

    return { score, searchWord: newSearchWord };
  }, { score: 0, searchWord: maxLenStr }).score / minKeyWords.length;

  const sortedMaxLenStr = Array.from(maxKeyWords.sort().join(''));
  const sortedMinLenStr = Array.from(minKeyWords.sort().join(''));

  const charScore = sortedMaxLenStr.reduce((oldItem, nItem, index) => { 
    const surroundingChars = [sortedMinLenStr[index-1], sortedMinLenStr[index], sortedMinLenStr[index+1]]
    .filter(char => char != undefined);
    
    return surroundingChars.includes(nItem)? oldItem + 1 : oldItem
  }, 0) / maxLength;

  const score = (lenScore * .15) + (orderScore * .25) + (charScore * .25) + (keywordScore * .35);

  return score;
}

【讨论】:

    【解决方案2】:

    尝试:

    =ARRAYFORMULA(IFERROR(IF(LEN(
     REGEXREPLACE(REGEXREPLACE(LOWER(A1:A), "[^a-z ]", ), 
     LOWER("["&B1:B&"]"), ))>0, "mismatch", )))
    

    【讨论】:

    • 我从来没有想过使用床单公式 subarashii 是可能的。
    【解决方案3】:

    通过 Google 表格公式实施模糊匹配将很困难。如果您想一次填充所有行,我建议为此使用自定义公式或完整的脚本(均通过 Google Apps 脚本)。

    自定义公式:

    function fuzzyMatch(string1, string2) {
      string1 = string1.toLowerCase()
      string2 = string2.toLowerCase();
      var n = -1;
    
      for(i = 0; char = string2[i]; i++)
        if (!~(n = string1.indexOf(char, n + 1))) 
          return 'Mismatch';
    };
    

    这样做的目的是比较第二个字符串的字符顺序是否与第一个字符串的顺序相同。有关返回不匹配的情况,请参见下面的示例数据。

    输出:

    笔记:

    • 最后一行不匹配,因为第二个字符串中有 r,但在第一个字符串中找不到,因此不符合正确的顺序。
    • 如果这不符合您的测试用例,请添加一个更明确的列表,该列表将显示公式/函数的预期输出,以便对其进行调整,或者查看 player0 的答案,该答案仅使用 Google 表格公式并且不太严格条件。

    参考:

    【讨论】:

      【解决方案4】:

      传统模糊匹配的主要限制是它没有考虑字符串之外的相似性。主题聚类需要语义理解。 Goodlookup 是电子表格用户的智能功能,非常接近语义理解。它是一个预训练模型,具有 GPT-3 的直觉和模糊匹配的连接能力。像 vlookup 或索引匹配一样使用它来加速您在 google 表格中的主题聚类工作。

      https://www.goodlookup.com/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-26
        • 2011-01-18
        • 2015-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-11
        • 2021-10-17
        相关资源
        最近更新 更多