降低这个公式的复杂性?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了降低这个公式的复杂性?相关的知识,希望对你有一定的参考价值。

我有一个关于优化我在Google表格中使用的公式的问题:

=ARRAYFORMULA(
  IF(
    IFERROR(
      MATCH($B2 & A2, ($B$1:B1) & ($A$1:A2), 0),
      0
    ) = 0,
    1,
    0))

该公式通过计算列A(ID)中的所有唯一值来计算,因为它出现在列B(日期)的日期范围内,以在列C(计数)中给出输出。

注意计数值是如何仅为0和1,并且如果它是ID在日期范围中的第一次出现,则仅显示1。

以下示例数据。

ID  Date    Count
138 Oct-13  1
138 Oct-13  0
29  Oct-13  1
29  Nov-13  1
138 Nov-13  1
138 Nov-13  0

问题是,一旦我获得超过10000行进行解析,该公式就会慢慢地进行计算,并且需要花费一个多小时来完成计算。我想知道是否有人建议如何优化这个公式,所以我不需要让它运行这么长时间。

谢谢,

答案

我一直在玩一些公式,我认为这个更好,但在10000行之后仍然变得非常慢。

=IF(COUNTIF((FILTER($A$1:$A2, $B$1:$B2 = $B2)),$A2) = 1, 1, 0)

编辑

以下是Google产品论坛上发布的附加公式,只需将其放入一个单元格中,然后自动填充。这是我到目前为止找到的最佳答案。

=ArrayFormula(IF(LEN(A2:A),--(MATCH(A2:A&B2:B,A2:A&B2:B,0)=ROW(A2:A)-1),))

另一答案

我无法找到一个只有公式的解决方案,我可以说它胜过你所拥有的。但是,我确实提出了一个在线性时间内运行的自定义函数,所以它应该表现良好。我很想知道它与你的最终解决方案相比如何。

/**
 * Returns 1 for rows in the given range that have not yet occurred in the range,
 * or 0 otherwise.
 *
 * @param {A2:B8} range A range of cells
 * @param {2} key_col Relative position of a column to key by, e.g. the sort
 *   column (optional; may improve performance)
 * @return 1 if the values in the row have not yet occurred in the range;
 *   otherwise 0.
 * @customfunction
 */
function COUNT_FIRST_OF_GROUP(range, key_col) {
  if (!Array.isArray(range)) {
    return 1;
  }

  const grouped = {};

  key_col = typeof key_col === 'undefined' ? 0 : key_col - 1; // convert from 1-based to 0-based

  return range.map(function(rowCells) {
    const group = groupFor_(grouped, rowCells, key_col);
    const rowStr = JSON.stringify(rowCells); // a bit of a hack to identify unique rows, but probably a good compromise
    if (rowStr in group) {
      return 0;
    } else {
      group[rowStr] = true;
      return 1;
    }
  });
}

/** @private */
function groupFor_(grouped, row, key_col) {
  if (key_col < 0) {
    return grouped; // no key column; use one big group for all rows
  }

  const key = JSON.stringify(row[key_col]);
  if (!(key in grouped)) {
    grouped[key] = {};
  }
  return grouped[key];
}

要使用它,请在Google表格中转到工具>脚本编辑器...,将其粘贴到编辑器中,然后点击保存。然后,在电子表格中,使用如下函数:

=COUNT_FIRST_OF_GROUP(A2:B99, 2)

它将自动填充范围内的所有行。你可以see it in action here

另一答案

如果满足某些假设,比如,1。相同的ID号总是一起出现(如果没有,也许你可以先按ID排序,然后再排除日期),然后,

=ARRAYFORMULA(1*(A2:A10000&B2:B10000<>A1:A9999&B1:B9999))

如果日期被识别,我认为你可以使用+而不是&。同样,在这里和那里做出了各种假设。

以上是关于降低这个公式的复杂性?的主要内容,如果未能解决你的问题,请参考以下文章

数论公式总结

如何降低以下代码块的时间复杂度?

斯特林公式的证明

如何降低排序的时间复杂度?

以下代码片段的算法复杂度

重构此函数以降低其在 if else 条件下的认知复杂性