如何从 Google 工作表中不断增长的字符串列表中找到与字符串最接近的匹配项?

How to find the closest match to a string from ever-growing list of strings in Google sheets?

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

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

详情:

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

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

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

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

代码片段:

// 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)。

示例: