【问题标题】:Efficient cell formula counting of substrings in a range of cells对一系列单元格中的子字符串进行有效的单元格公式计数
【发布时间】:2017-11-01 18:16:52
【问题描述】:

我有一个包含两列的 Google 电子表格:A 和 C。A 列在其自己的单元格中有超过一千行名称/主题,而 C 列有数百行,其中包含上述名称/主题的可变组合它的各个单元格,每个名称/主题用分号与其他单元格分隔。这些列中的每一个都在一天中频繁地获得新条目。

作为一个非常简化的设置视觉示例:

**Column A: Names  | Column B: Occurrences | Column C: List**

A2: Adam           | B2: [Blank]           | C2: Charles; Adam

A3: Bob            | B3: [Blank]           | C3: Adam

A4: Charles        | B4: [Blank]           | C4: Smith, Charles

A5: Smith, Charles | B5: [Blank]           | C5: Bob Evans

A6: Bob Evans      | B6: [Blank]           | C6: Smith, Charles; Charles; Bob

A7: [etc.]         | B7: [Blank]           | C7: Bob Evans; Charles; Bob

A8: [etc.]         | B8: [Blank]           | C8: [etc.] 

目前,我正在使用以下公式来计算 A 列(此处为 A2)中的每个字符串作为 C 列(此处为 C2 到 C7)中的子字符串出现的次数:

=ARRAYFORMULA(IF(A2="","",(SUMPRODUCT(REGEXMATCH(REGEXREPLACE(REGEXREPLACE($C$2:$C$7,"([\(\)\?])", ""),"(\w+),{0,1}\s+(\w+)","$1$2"),".*(^|\s)"& trim(REGEXREPLACE(REGEXREPLACE($A2,"([\(\)\?])", ""),"(\w+),{0,1}\s+(\w+)","$1$2"))&"(;|$).*")))))

这给出了正确的总数,但是一旦你扩大规模,它似乎处理得非常繁重;更改或添加任何一个条目到 C 列会导致整个工作表重新计算其数千个条目,并且需要几分钟才能得出新的总数。此处使用了许多 REGEXREPLACE 值,因为某些条目具有诸如“()”和“?”之类的标点符号,因为诸如“Erōs”,“Olympic Games(23rd : 1984 : Los Angeles, Calif.)”之类的单元格,和“Thomas, Aquinas, Saint, 1225?-1274”。

我想出的最接近的计数方法如下:

=SUMPRODUCT((LEN(C$2:C$7)-LEN(SUBSTITUTE(C$2:C$7,A2,"")))/LEN(A2))

测试表明,这个简单得多的公式可以在几秒钟内重新计算整个工作表,但它实际上并不能正确计算条目。在上面的 C2-C7 示例中,“Bob”和“Charles”的总数为 4 和 5,因为它不区分“Bob”和“Bob Evans”或“Charles”和“Smith, Charles”。 ”它应该分别正确找到 2 和 3。

有没有一种有效的方法来调整上述公式或创建一个新的公式来正确计算所有子字符串 - 将总和限制为与 A 列完全匹配,因为它们在 C 列的分号之间找到 - 而不会导致工作表的计算一次冻结几分钟?正则表达式是我最初最终采取的路线,但我认为这些操作是需要这么长时间的原因。

【问题讨论】:

    标签: regex count google-sheets formulas array-formulas


    【解决方案1】:

    试试
    B2:

    =SUMPRODUCT(TRIM(A2)=TRIM(SPLIT($C$2:$C$8,";")))
    

    【讨论】:

    • 这太棒了,是的!我唯一的问题是是否有办法让它搜索无限范围而不返回错误。使用 ($C$2:$C) 而不是 ($C$2:$C$8) 会得到 #VALUE 的结果,“错误函数 SPLIT 参数 1 值应该是非空的。”我还没有找到正确的方法来分层 IF 语句来管理它。
    • C$2:INDEX(C$2:C, CountA(C$2:C))C$2:C&" " 第一个提供更好的性能(如果你能弄清楚如何使用它)。如果您只想计算每个唯一实体的数量,请在下面查看我的其他解决方案。
    • 我相信成功了;非常感谢您的帮助!
    【解决方案2】:

    这可能会让你朝着正确的方向开始:

    =QUERY(C$2:C,"SELECT count(C) WHERE C CONTAINS ('"&A2&"') OR C CONTAINS upper('"&A2&"') OR C CONTAINS lower('"&A2&"')", -1)
    

    【讨论】:

    • 你可以把它全部放在上面以简化。 =QUERY(C$2:C,"SELECT count(C) WHERE upper(C) CONTAINS upper('"&A2&"') ")
    • 这两个看起来对准确计数非常有帮助,但是当我将任一公式放在 B1 中时,它只会增加 B2 中“亚当”出现的次数,而不是计算每一列 A 实例和在相应的 B 单元格中显示它们的总和。恐怕我对 SQL 和 Google 查询不够熟悉,无法识别问题。
    • 简单修复,查询函数喜欢标记它的数据集,所以关闭它是:=QUERY(C$2:C,"SELECT count(C) WHERE C CONTAINS ('"&A2&"') OR C CONTAINS upper('"&A2&"') OR C CONTAINS lower('"&A2&"') label count(C) ''",)
    【解决方案3】:

    也试试这个:
    在某处 Y1:

    =QUERY(ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(CONCATENATE(SPLIT(C2:C6,";")& "?"), "?")))), "select Col1,Count (Col1) group by Col1")
    

    【讨论】:

    • 漂亮的方法。 & "?"), "?") 中的网球拍表情符号在这里有什么用途?
    • @A. K. 它是一个独特的差异化实体。公式需要在文本上添加一个唯一的标记,以便在将它们合并为一个后将它们分开。我也可以使用% 或任何其他符号。但是,您的文本中也可能有%。如果是这样,公式将失败。但我相信你的文字中不可能有网球拍表情符号。你?吗?
    • 我认为可能是这样;感谢您的澄清!
    猜你喜欢
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多