【问题标题】:How to find the closest match to a string from ever-growing list of strings in Google sheets?如何从 Google 表格中不断增长的字符串列表中找到与字符串最接近的匹配项?
【发布时间】:2021-05-11 08:14:00
【问题描述】:

这个问题有点复杂,所以我创建了这个图像: Question Scenario

你可以找到the sample spreadsheet here. 为了清楚起见,我用字母代替了实际数据。

详情:

  • 我有 10 个固定条件,每个条件都有特定的权重。

  • 可以通过多种方式组合条件,从而创建大量可能的组合。我通过序列化将其减少到不到 1000 个。此列称为“所有条件”。

  • 可用条件”列显示可用的可能组合列表。此列表将继续增长,直到与“所有条件”列完全匹配。

挑战是: 考虑到权重,如何从“可用条件”中找到与“所有条件”中每个值最接近的匹配项?

例如,由于 'A, B' 可用,它将匹配。但是对于“A,B,C”,我们需要找到“A,B,C”或可用权重最高的组合,即“A,B”。

【问题讨论】:

  • 不确定我是否了解查找最接近匹配项的标准。我知道Weight 将被使用,但如何?条件的顺序在这里重要吗? (例如,如果我们有 ABC,AB 可能是紧密匹配,但不是 BA?)
  • 是的,你是对的 - 对于 ABC,AB & BC 将是两个选项,由于 AB 的权重较高,因此将使用 AB。无法使用 BA 和 CB,因为在此步骤之前已通过从可能的组合进行序列化来过滤它们。因此,条件的顺序很重要。

标签: google-apps-script google-sheets google-sheets-formula spreadsheet


【解决方案1】:

您可以使用 Apps 脚本 custom function 执行以下操作:

  • 获取所有available 组合、fixed 条件和All 组合(这可以作为自定义函数参数接收)。将逗号分隔的字符串拆分为具有所有不同条件(AB 等)的数组。
  • 循环遍历All 组合,并为每个组合执行以下操作:
  • 启动 while 循环,循环遍历组合中的每个条件,并过滤掉不匹配的条件,直到 (1) 到达数组末尾并找到完全匹配,或 (2) 不匹配找到了,并且有一个候选人名单。
  • 在可能的候选者中(如果未找到匹配项),找到组合权重最大的候选者。
  • 返回所有最佳匹配项。

代码sn-p:

// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
function GET_CLOSEST_COMBOS(range) {
  const sheet = SpreadsheetApp.getActiveSheet();
  const available = sheet.getRange("A2:B").getValues().filter(row => row[0] !== "")
                         .map(row => [commaSeparatedToArray(row[0]), row[1]]);
  const fixedConditions = available.filter(av => av[1] !== "");
  const conditions = range.flat().map(conditionString => commaSeparatedToArray(conditionString));
  const bestMatches = conditions.map(condition => {
    let i = 0;
    let currentAvailable = [...available];
    while (i < condition.length) {
      const matchExists = currentAvailable.some(av => av[0][i] == condition[i]);
      if (matchExists) {
        currentAvailable = currentAvailable.filter(av => av[0][i] == condition[i]);
      } else {
        currentAvailable = currentAvailable.filter(av => av[0].length - 1 !== i);
      }
      if (!matchExists || (matchExists && i === condition.length - 1)) {
        const candidates = currentAvailable.map(av => {
          const weight = av[0].reduce((acc, current, index) => {
            return acc + fixedConditions.find(cond => cond[0] == current)[1];
          }, 0);
          return [av[0], weight];
        });
        const bestMatch = candidates.reduce((max, candidate) => max[1] >= candidate[1] ? max : candidate);
        return bestMatch[0].join(", ");
      }
      i++;      
    }
  });
  return bestMatches;
}

function commaSeparatedToArray(conditionString) {
  return conditionString.split(",").map(condition => condition.trim());
}

在脚本中定义后,您可以像使用任何工作表内置函数一样使用它。此函数接受与您要检索最佳匹配的All combinations 对应的范围(在本例中为D2:D)。

示例:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    相关资源
    最近更新 更多