Вычисление экземпляров между двумя значениями - PullRequest
0 голосов
/ 22 сентября 2018

Как лучше всего рассчитать самое большое количество последовательных «k» в таблице ниже в excel?Я не просто хочу подсчитать общее количество «k», я хочу определить самую длинную строку из «k» в строке между «c» (например, строки 1 и 2 будут равны «4»)).Заранее спасибо!

Table 1

Ответы [ 5 ]

0 голосов
/ 22 сентября 2018

ОК, я ошибся, использовать функцию частоты не так просто.

Вы бы, по крайней мере, должны были игнорировать любые k, оставшиеся на каждом конце диапазона (они не заключены в c):

=MAX(FREQUENCY(IF(B2:M2="k",COLUMN(B2:M2)),IF(B2:M2="c",COLUMN(B2:M2)))*(ROW(A1:INDEX(A:A,COUNTIF(B2:M2,"c")+1))>1)*(ROW(A1:INDEX(A:A,COUNTIF(B2:M2,"c")+1))<=COUNTIF(B2:M2,"c")))

, которая является формулой массива.

enter image description here

Тогда, если вы хотите игнорировать k, которые были между c, нобыли перемежены с другими символами (например, 'u'), потребовалось бы другое условие:

=MAX(FREQUENCY(IF(B4:M4="k",COLUMN(B4:M4)),IF(B4:M4="c",COLUMN(B4:M4)))
*(FREQUENCY(IF(B4:M4<>"k",COLUMN(B4:M4)),IF(B4:M4="c",COLUMN(B4:M4)))=1)
*(ROW(A$1:INDEX(A:A,COUNTIF(B4:M4,"c")+1))>1)* 
(ROW(A$1:INDEX(A:A,COUNTIF(B4:M4,"c")+1))<=COUNTIF(B4:M4,"c")))

'= 1' во второй строке формулы объясняется тем, что <> "k" включает в себя "c",так что вы всегда получите хотя бы один счет.

enter image description here

0 голосов
/ 22 сентября 2018

Если вы не против использования VBA, вы можете использовать регулярные выражения.Приведенный ниже UDF позволяет вам ввести в качестве аргумента либо строку, либо диапазон ячеек.

Он ищет последовательность ck, за которой следует любое количество k, а затем следуетc и возвращает длину максимальной длины (-1 для учета ведущей подстроки c), которая соответствует

Option Explicit
Function CountCKKC(myData) As Long
    Dim RE As Object, MC As Object, M As Object
    Const sPat As String = "ck{1,}(?=c)"
    Dim s As String, c As Range
    Dim L As Long

Select Case TypeName(myData)
    Case "Range"
        s = ""
        For Each c In myData
            s = s & c.Value2
        Next c
    Case "String"
        s = myData
    Case Else
        Debug.Print TypeName(myData)
        Stop
End Select

Set RE = CreateObject("vbscript.regexp")
With RE
    .Pattern = sPat
    .Global = True
    .IgnoreCase = True
    If .Test(s) = True Then
        Set MC = .Execute(s)
        For Each M In MC
            L = IIf((M.Length - 1) > L, M.Length - 1, L)
        Next M
    End If
End With

CountCKKC = L

End Function
0 голосов
/ 22 сентября 2018

Если вам нужно в одной клетке, это будет немного сложно.Проверьте это.

=MAX(--((COLUMN($B2:$N2)-(TRANSPOSE(COLUMN($B2:$N2)))+1)=
         COUNTIF(INDIRECT("R"&ROW($B2)&"C"&TRANSPOSE(COLUMN($B2:$N2))&
                          ":R"&ROW($B2)&"C"&COLUMN($B2:$N2),FALSE),"k"))*
        (COLUMN($B2:$N2)-(TRANSPOSE(COLUMN($B2:$N2)))+1))

Это формула массива , поэтому, пожалуйста, нажмите Ctrl + Shift + Enter , чтобы завершить ее.Как только вы добились успеха, вы увидите {} вне формулы.

Ключ: максимальное число последовательных «k» s, которое начинается с rngA до rngB, равно ячейкамсчитается от rngA до rngB.Поэтому я построил матрицу * n, чтобы проверить 1. количество ячеек и 2. число «k».

Предупреждения: Это матрица * n, так что если вы кормитеслишком много данных, таких как 10000 столбцов, это может быть очень медленно.

enter image description here

0 голосов
/ 22 сентября 2018

UDF для листа с использованием регулярных выражений.Вы передаете один диапазон строк в качестве первого аргумента, rng, и букву, которая идет с обеих сторон как boundingLetter, и букву, которая идет внутрь как targetLetter.. Вы хотите посчитать "k" между "гр "s.Таким образом, «k» будет targetLetter, а «c» - boundingLetter.Поскольку они передаются в качестве параметров, их можно легко изменить.

Option Explicit
Public Sub Test()
    Dim boundingLetter As String, targetLetter As String, rng As Range

    Set rng = [C2:V2]
    boundingLetter = "c"
    targetLetter = "k"

    Debug.Print GetMaxSequence(rng, boundingLetter, targetLetter)
End Sub

Public Function GetMaxSequence(ByVal rng As Range, ByVal boundingLetter As String, ByVal targetLetter As String) As Variant
    Dim arr(), matches As Object, iMatch As Object, inputString As String, finalString As String, maxLength As Long

    If rng.Count < 3 Or rng.Rows.Count > 1 Then
        GetMaxSequence = CVErr(xlErrNA)
        Exit Function
    End If

    arr = rng.Value
    arr = Application.Index(arr, 1, 0)

    If IsError(arr) Then
        GetMaxSequence = CVErr(xlErrNA)
        Exit Function
    End If

    inputString = Join(arr, Chr$(44))

    With CreateObject("vbscript.regexp")
        .Global = True
        .MultiLine = True
        .IgnoreCase = True
        .Pattern = boundingLetter & ",(" & targetLetter & ",)+" & boundingLetter

        If .Test(inputString) Then
            Set matches = .Execute(inputString)
            For Each iMatch In matches
                If Len(iMatch) > maxLength Then
                    maxLength = Len(iMatch)
                    finalString = iMatch
                End If
            Next iMatch
        Else
            GetMaxSequence = CVErr(xlErrNA)
            Exit Function
        End If
        .Pattern = boundingLetter & "|,"
        GetMaxSequence = Len(.Replace(finalString, vbNullString))
    End With
End Function

На листе:

enter image description here

0 голосов
/ 22 сентября 2018

Вам понадобится дополнительный ряд промежуточных вычислений, но это не так сложно,

простой if и счетчик:

=IF(B$2="k",1,0)+A$2

Где

 A2 = 0

Затем в последней ячейке строки вы должны максимально увеличить диапазон:

=MAX(B2:B10) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...