Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1
RSS
Максимальные расстояния между одинаковыми знаками строки
 
Уважаемые, помогите пожалуйста справиться с этим -
Расстояния максимальные между одинаковыми знаками строки
Задача. В строках, для каждого из знаков «i», «x», «z» подсчитать максимальное расстояние между двумя одинаковыми знаками.
Для знака i мах расстояние = 3          iixzizzixxziix
Для знака x мах расстояние = 5         iixzizzixxziix
Для знака z мах расстояние = 3         iixzizzixxziix

Изменено: Рубикон - 20 ноя 2020 22:12:16
 
Доброе время суток.
Вариант на Power Query.
 
Цитата
Для знака i
UDF
Код
Function Kol_vo(cell As String) As Integer
Dim mo As Object
Dim n As Integer
 With CreateObject("VBScript.RegExp")
   .Global = True
   .IgnoreCase = True
   .MultiLine = True
   .Pattern = "i[^i]+i"
     If .test(cell) Then
       Set mo = .Execute(cell)
         Kol_vo = Len(mo(0)) - 2
       For n = 1 To mo.Count - 1
         If Len(mo(n)) - 2 > Kol_vo Then
           Kol_vo = Len(mo(n)) - 2
         End If
       Next
    End If
 End With
End Function
 
PQ
Код
 let
    g=(x,y)=> {x,if y{0}<>0 then List.Max({y{1},x-y{0}-1}) else 0} ,
    f=(x)=> List.Accumulate(    Text.ToList(x),
                                [j=0,x={0,0},i={0,0},z={0,0},r=[]],
                                (s,c)=>
                                [j=s[j]+1,
                                x= if c = "x" then g(j,s[x]) else s[x],
                                i= if c = "i" then g(j,s[i]) else s[i],
                                z= if c = "z" then g(j,s[z]) else s[z],
                                r=[i=i{1},x=x{1},z=z{1}]]
                            )[r],
    
    from = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],
    tbl = Table.TransformColumns(from,{"знаки строки",f}),
    to = Table.ExpandRecordColumn(tbl, "знаки строки", {"i", "x", "z"})
in
    to
Каждому For свой Next
 
Код
' найти максимальное расстояние между символами F в тексте T
Function MaxDistanceBethFinT&(F$, T$)
  Dim re, ms, m
  Set re = CreateObject("VBScript.RegExp"): re.Global = True
  re.Pattern = F & "[^" & F & "]+" & F:  re.MultiLine = True
  If re.test(T) Then
    Set ms = re.Execute(T)
    For Each m In ms
      If m.Length - 2 > MaxDistanceBethFinT Then _
      MaxDistanceBethFinT = m.Length - 2
    Next
  End If
End Function
Изменено: Ігор Гончаренко - 20 ноя 2020 01:26:57
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Код
Function MaxDist(s As String, txt As String) As Long
    Dim i As Long, j As Long, m As Long
    i = InStr(txt, s)
    While i > 0
        j = InStr(i + 1, txt, s)
        If j - i - 1 > m Then m = j - i - 1
        i = j
    Wend
    MaxDist = m
End Function
 
Собственно все тоже что и всегда, но
1. Обрезка краюшек требуется :-(
2. X пришлось заменить на Икс, а то там Ха было
массивная

=IFERROR(MAX(FREQUENCY(IF(MID($B2;ROW(INDEX($A:$A;FIND(LOWER(RIGHT(C$1));$B2)):INDEX($A:$A;LEN($B2)-LEN(TRIM(RIGHT(SUBSTITUTE(LOWER($B2);LOWER(RIGHT(C$1));REPT(" ";99));99)))));1)<>LOWER(RIGHT(C$1));ROW(INDEX($A:$A;FIND(LOWER(RIGHT(C$1));$B2)):INDEX($A:$A;LEN($B2)-LEN(TRIM(RIGHT(SUBSTITUTE(LOWER($B2);LOWER(RIGHT(C$1));REPT(" ";99));99))))));
IF(MID($B2;ROW($1:$98);1)=LOWER(RIGHT(C$1));ROW($1:$98))));"")
Изменено: БМВ - 20 ноя 2020 08:56:09
По вопросам из тем форума, личку не читаю.
 
В "Избушку" перенесем?
Есть формульное решение - 101 99 символов
Изменено: MCH - 20 ноя 2020 10:39:14
 
Тохе хотел строковыми попробовать. Получилось по скорости также или незаметно быстрее, чем у MCH
2 функции и тестовый стенд
Результаты прогона 1 млн раз строки "iixzizzixxziix": не более 0,5 сек для поиска максимального расстояния между каждым символом

P.S.: Рубикон, отредактируйте ваше сообщение - не надо писать через строку или с такими огромными отступами
Изменено: Jack Famous - 20 ноя 2020 09:55:13
Реквизиты для благодарности и контакты для связи — в профиле
 
Цитата
Jack Famous написал:
получилось по скорости также или незаметно быстрее
не увидел принципиальной разницы в алгоритме
 
Цитата
MCH: не увидел принципиальной разницы
потому что её нет  :D
Здравствуйте, Михаил! Я просто написал свой вариант, а потом увидел ваш и решил сравнить по скорости - разницы практически нет: 441-476 / 296-316 / 335-367 для символов ixz соответственно (время в мс на 1млн чуууууууть быстрее, но в пределах погрешности)
Реквизиты для благодарности и контакты для связи — в профиле
 
Цитата
MCH написал:
В "Избушку" перенесем?
Краюшки обрезает? Если да то можно посмотреть. Я особо не изголялся.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
Краюшки обрезает? Если да то можно посмотреть.
У меня полное соответствие результатов UDF и формулы
 
MCH, Тезка, если не в избушку, то мне интересно. Утром по быстрому только то получилось, больше не смог уделить времени.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
если не в избушку, то мне интересно
Тёзки, мне тоже интересно  :) , но нужно время - хотя бы выходные посидеть
Изменено: buchlotnik - 20 ноя 2020 15:34:01
Каждому For свой Next
 
Массивка 95 в ENG стиле.
=MAX(IFERROR(SEARCH(RIGHT(C$1);MID($B2;SEARCH(RIGHT(C$1);$B2);99);ROW($2:$99))-ROW($2:$99);))

и 90 также с ENG появился
=MAX(;IFERROR(SEARCH(RIGHT(C$1);$B2;ROW($2:$99))-SEARCH(RIGHT(C$1);$B2;ROW($1:$98))-1;))

С русскими замена ПРАВСИМВ на ПРАВБ   98 с учетом {}
Изменено: БМВ - 20 ноя 2020 18:16:04
По вопросам из тем форума, личку не читаю.
 
Есть 76, вскрываемся или в избушку перенести вопрос?
 
Да выкладывай, я уже, тем более что не понятно что сравниваем. если не извлекать символ искомый из заголовка то естесвенно короче .... то есть решение для предложенной таблицы которое можно протянуть сравниваем?
Изменено: БМВ - 20 ноя 2020 18:19:12
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
если не извлекать символ искомый из заголовка то естесвенно короче
да, не извлекал, а прописал в заголовках. Соответственно короче, сделал еще немного короче за счет МУМНОЖ:
Код
=МАКС(МУМНОЖ(ЕСЛИОШИБКА(ПОИСК(C$1;$B2;СТРОКА($1:$98)+{0;1})+{1;0};);{-1:1}))
Изменено: MCH - 20 ноя 2020 18:32:07
 
быстродействие сравнивать не будем, MMULT проиграет :-)
Тезка, только так не лучше?
=MAX(;MMULT(IFERROR(SEARCH(E$1;$B9;ROW($1:$98)+{0\1}););{-1;1})-1)
=МАКС(;МУМНОЖ(ЕСЛИОШИБКА(ПОИСК(C$1;$B2;СТРОКА($1:$98)+{0;1}););{-1:1})-1)
Изменено: БМВ - 20 ноя 2020 18:51:48
По вопросам из тем форума, личку не читаю.
 
Off. Об Избушке. Я когда-то писал одному из уважаемых модераторов, как сделать правила подсчета результатов "международными" (чтобы они не зависели от изобретателей и переводчиков имен функций Excel, как в этой теме) но мой глас остался без ответа. Если интересно, могу написать в Избушке.
Изменено: sokol92 - 20 ноя 2020 19:40:43
Владимир
 
Цитата
БМВ написал:
только так не лучше?
Наверно лучше, немного не дожал
 
Off
Владимир, лично мое мнение, хороша не только короткая , но и эффективно быстрая формула. Спасибо тезке, толкнул на размыслить и поискать совершенно иной подход.

И как водится замер скорости на 136000 строк

Скрытый текст


но стоило ввести ограничение по количеству символов, которое обсчитывается и
Скрытый текст


А вот что происходит, если делать замер длинны и как все меняется.
Скрытый текст
Изменено: БМВ - 20 ноя 2020 22:53:03
По вопросам из тем форума, личку не читаю.
 
БМВ спасибо! Ваши формулы самые быстрые!
Function работают оч. медленно, однако было интересно и тоже оч. благодарен.
Удивительные люди на форуме!
 
Код
Sub MaxDistanceBethFinT()
  Const f$ = "i"
  Dim re, ms, m, t, tm#, r&
  tm = Timer: t = [a1].CurrentRegion
  Set re = CreateObject("VBScript.RegExp"): re.Global = True
  re.Pattern = f & "[^" & f & "]+" & f:  re.MultiLine = True
  For r = 1 To UBound(t)
    If re.test(t(r, 1)) Then
      Set ms = re.Execute(t(r, 1)): t(r, 1) = 0
      For Each m In ms
        If m.Length - 2 > t(r, 1) Then t(r, 1) = m.Length - 2
      Next
    End If
  Next
  [c1].Resize(UBound(t), 1) = t
  MsgBox Timer - tm
End Sub
у меня на компьютере около 2.5 сек
136 тыс ячеек колонки А заполнены этим: iixzizzixxziix

или заточенная под эту задачу процедура
Код
[/CODE][SPOILER][CODE]Sub MaxDistanceBethFinT()
  Const f$ = "i"
  Dim m&, mm&, t, tm#, r&, p1&, p2&
  tm = Timer: t = [a1].CurrentRegion
  For r = 1 To UBound(t)
    p1 = InStr(t(r, 1), f): mm = 0
    Do
      If p1 < Len(t(r, 1)) Then p2 = InStr(p1 + 1, t(r, 1), f)
      m = p2 - p1 - 1: If m > mm Then mm = m
      If p2 = 0 Then Exit Do Else p1 = p2
    Loop
    t(r, 1) = mm
  Next
  [c1].Resize(UBound(t), 1) = t
  MsgBox Timer - tm
End Sub
[/SPOILER]с временем работы 0.9 сек
Изменено: Ігор Гончаренко - 21 ноя 2020 02:22:03
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Рубикон написал:
Function работают оч. медленно,
Это странно. в общем случае функция из #6 работает быстрее и начинает отставать только при фиксированной и известной  длине обрабатываемой строки.  

Ігор Гончаренко,  Игорь, но у тебя не функция, для замеров нужно использовать этот алгоритм в функции и её с листа вызывать.
По вопросам из тем форума, личку не читаю.
 
БМВ Ігор Гончаренко спасибо Вам и Людям принявшим участие в обсуждении! Мой чайник как мог так и сварил, а "заключения" по поводу скорости обработки, что чай без заварки и сахара, и не надо обращать внимания.  Попробую разобраться с быстродействием функций...  
 Меня вполне устраивают рабочие формулы!  Еще раз СПАСИБО!
Изменено: Рубикон - 21 ноя 2020 23:04:38
 
Что-то я опять поздно проснулся.
Если есть уверенность, что символ встречается больше одного раза, то можно воспользоваться формулой:
=АГРЕГАТ(14;6;ПОИСК(ПРАВБ(C$1);$B2;СТРОКА($1:$99))-СТРОКА($1:$99);1)
*Неправильная формула.
Изменено: Светлый - 24 ноя 2020 08:08:32
 
Цитата
БМВ написал:
только так не лучше?
Можно еще на пару символов сократить:
Код
=МАКС(МУМНОЖ(ЕСЛИОШИБКА(ПОИСК(C$1;{0;""}&$B2;СТРОКА($2:$99)););{-1:1}))
Страницы: 1
Читают тему (гостей: 1)
Наверх