Страницы: 1
RSS
Подсчитать количество вхождений подстроки в массиве строк
 
Помогите придумать формулу, которая бы подсчитывала количества вхождений подстроки сразу в нескольких строках (т.е. ячейках). Пример прикрепляю. Ситуация осложняется тем, что например подстрока "AGA" в строке "KAGAGAL" встречается ДВА раза.
 
dim284, VBA разрешено?  :)
Цитата
dim284: подстрока "AGA" в строке "KAGAGAL" встречается ДВА раза.
перекрываться может только одна буква? Это не проблема, потому что всегда можно предварительно заменить "AGAGA "на "AGA_AGA", пока не кончатся…
Изменено: Jack Famous - 27.05.2024 18:38:26
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
VBA разрешено?
Сколько душе угодно :)
Да, перекрывается только одна буква. Но универсальность приветствуется.
 
Попробуйте так
Код
Sub GetFragment()
Dim n As Integer
Dim i As Long
Dim iLastRow As Long
Dim Kol_vo As Long
 iLastRow = Cells(Rows.Count, 1).End(xlUp).Row
  Kol_vo = 0
  For i = 1 To iLastRow
     n = InStr(1, Cells(i, 1), "AGA")
    If n > 0 Then
      Kol_vo = Kol_vo + 1
      Do
        n = InStr(n + 1, Cells(i, 1), "AGA")
        If n = 0 Then Exit Do
        Kol_vo = Kol_vo + 1
      Loop While n <> 0
    End If
  Next
    MsgBox "В столбце А ""AGA"" встречается: " & Kol_vo & " раз"
End Sub
 
Kuzmich, Ваш макрос работает. А можно его превратить в более удобный вариант, пользовательскую функцию например?
 
UDF
Код
Function Get_AGA(cell As String) As Integer
Dim n As Integer
     n = InStr(1, cell, "AGA")
    If n > 0 Then
      Get_AGA = Get_AGA + 1
      Do
        n = InStr(n + 1, cell, "AGA")
        If n = 0 Then Exit Do
        Get_AGA = Get_AGA + 1
      Loop While n <> 0
    End If
End Function
 
Отличная функция, спасибо! Но получается, что можно считать только по одной ячейке. А можно ли сделать массив входных данных? Немного переделал.

Код
Function Get_AGA(cell As String, подстрока As String) As IntegerDim n As Integer
     n = InStr(1, cell, подстрока)
    If n > 0 Then
      Get_AGA = Get_AGA + 1
      Do
        n = InStr(n + 1, cell, подстрока)
        If n = 0 Then Exit Do
        Get_AGA = Get_AGA + 1
      Loop While n <> 0
    End If
End Function

Так-то можно считать и формулой:=СУММПРОИЗВ(--("AGA"=ПСТР(A1;ПОСЛЕД(ДЛСТР(A1)-2;1;1;1);3)))

Изменено: dim284 - 27.05.2024 21:26:08
 
Регулярка от ИИ:
Код
(?=(AGA))
 
=COUNT(1/(MID(A1:A2;SEQUENCE(1;MAX(LEN(A1:A2)));3)="AGA"))
По вопросам из тем форума, личку не читаю.
 
БМВ, спасибо! Отлично работает. В русском экселе
=СЧЁТ(1/(ПСТР(A1:A3;ПОСЛЕД(1;МАКС(ДЛСТР(A1:A3)));3)="AGA"))
 
Цитата
nilske: (?=(AGA))
прекрасный шаблон  :idea:
    Начинает подбор немедленно, а не после подстроки.
Добавил игнор регистра
Изменено: Jack Famous - 28.05.2024 09:51:57
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Jack Famous, мне кажется что-то у Вас всё сложно так реализовано с регуляркой, зачем здесь рекурсия
нет рекурсии, не проснулся, всё равно сложно )
неужели нельзя просто посчитать количество подгрупп, которые вернёт выражение
- просто вопрос, сам ещё не попробовал
Изменено: nilske - 28.05.2024 10:20:28
 
Цитата
nilske: неужели нельзя просто посчитать количество подгрупп, которые вернёт выражение
ну ведь так и есть  :D :
If RE.Test(x) Then Get_AGA_RE = Get_AGA_RE + RE.Execute(x).Count
    Остальное — цикл по всем областям диапазона, получение массива и цикл по всем элементам массива. Если без диапазона, то и была бы одна строка (две, если учесть вариант с игнором регистра).
    Вроде, ничего сложного  :)
Изменено: Jack Famous - 28.05.2024 10:31:31
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Jack Famous, а зачем одновременно два объекта RE и Reci, если на самом деле всегда используется только один?
 
Цитата
nilske: зачем одновременно два объекта RE и Reci
один для точного поиска, другой для поиска с игнором регистра (CI = CaseIgnore).
Цитата
nilske: всегда используется только один
очевидно, это не так.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Jack Famous, а, ну всё - открылись глаза
переделал, но лучше оригинала не получилось ))
критика приветствуется

Код
Function Get_AGA_RE(rng As Range, sFind$, Optional CaseIgnore As Boolean) As Long
    Dim x, arr, a&
    Dim s$, REci    As RegExp, cell

    Set REci = New RegExp
    REci.Global = True
    REci.Pattern = "(?=(" & sFind & "))"
    REci.IgnoreCase = CaseIgnore

    For Each cell In rng:
        s = s & cell.Value2

    Next cell
    If REci.Test(s) Then Get_AGA_RE = REci.Execute(s).Count

End Function


сразу вижу сам - сцеплять значения лучше через разделитель
Изменено: nilske - 28.05.2024 14:01:52
 
Цитата
nilske: критика приветствуется
ну погнали тогда  :)
    1. скорость будет заметно ниже на больших объёмах — я же не просто так использовал цикл по массиву вместо цикла по ячейкам.
    2. идея собрать одну большую строку — хорошая  :idea: . Так не нужно помещать в статику 2 объекта регулярок. Но тогда нужно собирать строки в строковый массив (Dim a$() ) и итоговую строку получить как Join(a). Так может быть выигрыш, но надо проверять с разным количеством ячеек и длин строк. Накопление строки сцепкой (как у вас) — очень плохо для большого количества строк.

Цитата
nilske: сразу вижу сам - сцеплять значения лучше через разделитель
разумеется. Всегда.  :idea:
    Иначе можем получить совпадения там, где их нет: конец одной строки + начало другой.
Изменено: Jack Famous - 28.05.2024 14:28:22
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Еще вариант
=СУММПРОИЗВ(ДЛСТР(ПОДСТАВИТЬ(A1:A3;"A";"AA"))-ДЛСТР(ПОДСТАВИТЬ(ПОДСТАВИТЬ(A1:A3;"A";"AA");"AGA"; )))/3
или (21-й офис)
=LET(_а;ПОДСТАВИТЬ(A1:A3;"A";"AA");СУММ(ДЛСТР(_а)-ДЛСТР(ПОДСТАВИТЬ(_а;"AGA";11))))
Страницы: 1
Наверх