Эффективный подсчет по формулам ячеек подстрок в диапазоне ячеек

У меня есть электронная таблица 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», «Олимпийские игры (23-е: 1984: Лос-Анджелес, Калифорния)», и «Фома, Аквинский, Святой, 1225? -1274».

Ближайший вариант подсчета, который я придумал, следующий:

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

Тестирование показывает, что эта гораздо более простая формула может пересчитать весь лист за несколько секунд, но на самом деле она неправильно подсчитывает записи. В приведенном выше примере C2-C7 он даст итоговые значения 4 и 5 для «Боба» и «Чарльза», потому что он не делает различий между «Бобом» и «Бобом Эвансом» или «Чарльзом» и «Смитом, Чарльзом». ” Он должен правильно найти 2 и 3 соответственно.

Есть ли эффективный способ скорректировать приведенную выше формулу или создать новую, которая будет правильно подсчитывать все подстроки - ограничивая суммы точными совпадениями в столбце A, поскольку они находятся между точками с запятой в столбце C - без остановки вычислений листа по несколько минут за раз? Регулярные выражения были тем путем, которым я сначала пошел, но я думаю, что именно эти операции являются причиной того, что они занимают так много времени.


person A. K.    schedule 01.11.2017    source источник


Ответы (3)


Попробуйте
B2:

=SUMPRODUCT(TRIM(A2)=TRIM(SPLIT($C$2:$C$8,";")))
person TheMaster    schedule 01.11.2017
comment
Отлично, да! Мой единственный вопрос: есть ли способ, чтобы он выполнял поиск в неограниченном диапазоне, не возвращая ошибку. Использование ($ C $ 2: $ C) вместо ($ C $ 2: $ C $ 8) дает результат #VALUE: «Значение параметра 1 SPLIT функции ошибки не должно быть пустым». Я не придумал, как правильно наложить оператор IF, чтобы справиться с этим. - person A. K.; 02.11.2017
comment
C$2:INDEX(C$2:C, CountA(C$2:C)) или C$2:C&" " Первый дает лучшую производительность (если вы можете понять, как его использовать). Если вам просто нужен подсчет каждого уникального объекта, посмотрите другое мое решение ниже. - person TheMaster; 02.11.2017
comment
Я считаю, что это помогло; Большое спасибо за вашу помощь! - person A. K.; 02.11.2017

Это может помочь вам начать в правильном направлении:

=QUERY(C$2:C,"SELECT count(C) WHERE C CONTAINS ('"&A2&"') OR C CONTAINS upper('"&A2&"') OR C CONTAINS lower('"&A2&"')", -1)
person warbirdn    schedule 01.11.2017
comment
Чтобы упростить, вы можете сделать все выше. =QUERY(C$2:C,"SELECT count(C) WHERE upper(C) CONTAINS upper('"&A2&"') ") - person TheMaster; 02.11.2017
comment
Они оба выглядят очень полезными для точного подсчета, но в тот момент, когда я помещаю любую формулу в B1, она только подтягивает количество вхождений Adam в B2 вместо того, чтобы считать для каждого экземпляра столбца A и отображать их суммы в соответствующих B-ячейках. Боюсь, я недостаточно знаком с SQL и Google Queries, чтобы определить проблему. - person A. K.; 02.11.2017
comment
Простое исправление, функция запроса любит помечать свой набор данных, поэтому для ее отключения используется: = QUERY (C $ 2: C, SELECT count (C) WHERE C CONTAINS ('& A2 &') OR C CONTAINS верхний ('& A2 &') ИЛИ C СОДЕРЖИТ нижний ('& A2 &') количество ярлыков (C) '',) - person warbirdn; 02.11.2017

Попробуйте и это:
Где-нибудь в Y1:

=QUERY(ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(CONCATENATE(SPLIT(C2:C6,";")& "????"), "????")))), "select Col1,Count (Col1) group by Col1")
person TheMaster    schedule 02.11.2017
comment
Отличный подход. Какой цели служит смайлик теннисной ракетки здесь, в & "????"), "????")? - person A. K.; 02.11.2017
comment
@A. К. Он служит уникальной дифференцирующей сущностью. Формуле нужен уникальный маркер на тексте, чтобы разделиться после их объединения в одно целое. Я мог бы также использовать % или любой другой символ. Но тогда у вас также может быть % где-то в вашем тексте. Если так, формула не сработает. Но я считаю, что у вас нет шансов найти смайлик с теннисной ракеткой где-нибудь в вашем тексте. Вы ...? - person TheMaster; 02.11.2017
comment
Я подумал, что это могло быть так; Спасибо за разъяснения! - person A. K.; 03.11.2017