Страницы: 1 2 След.
RSS
Функция для извлечения чисел из строки. Доработка и сравнение с RegExp.
 
Столкнулся с проблемой вытащить некоторые числа из строки. Тем много - но нормального решения так и не нашел. Написал свою функцию.
Прошу привести примеры на  Regexp для достижения такого же результата, чтобы убедится- есть ли смысл доделывать дальше свою функцию.
Изменено: Marat Ta - 12.03.2021 23:01:16
 
Поверь, RegExp будут лучше, но надо уметь писать паттерны (шаблоны)....
Ты пишешь - вытащить некоторые числа из строки: "Price 1 000 000.25 руб 2 500,325$ aed....1754-0025"
какие числа? Я вот, например, не понял, какое именно число ты хочешь достать из строки (какую группу чисел)  - все? 1-ю? 2-ю? 3-ю?
Изменено: New - 12.03.2021 22:53:41
 
Все 3 числа - я их выташил своей функций. Разделители с . , - =
с 1 000 000-05 (пробелами в целой части)
Рядом еще 2 варианта.

Просто привык к более простому и понятному алгоритму решения задач.
Изменено: Marat Ta - 12.03.2021 22:57:20
 
где 3 числа в твоём файле? можно более конкретно - номера ячеек, либо пальцами набери на клавиатуре, какие 3 числа ты вытащил?
Я из этой строки "Price 1 000 000.25 руб 2 500,325$ aed....1754-0025" - могу вытащить 23 числа

Цитата
Marat Ta написал:
Просто привык к более простому и понятному алгоритму решения задач.
аааа, тогда ОК
Изменено: New - 12.03.2021 22:59:31
 
Обновил файл.
Десятичные числа, а не цифры.
Изменено: Marat Ta - 12.03.2021 23:03:02
 
сейчас придёт дедушка Kuzmich и научит тебя Родину RegExp любить )
Изменено: New - 12.03.2021 23:22:51
 
Я так и думал, что только Kuzmich сможет ....)
Изменено: Marat Ta - 12.03.2021 23:31:10
 
Код
Function exec(t, n)
    With CreateObject("VBScript.RegExp")
        .Global = True
        .Pattern = "([\d\s]+)([-\.,]+)(\d+)"
        Set s = .Execute(t)(n - 1)
    End With
    exec = CDec(s.SubMatches(0) & Application.DecimalSeparator & s.SubMatches(2))
End Function
Изменено: buchlotnik - 12.03.2021 23:55:08
Соблюдение правил форума не освобождает от модераторского произвола
 
Marat Ta,
1. buchlotnik тоже может )
2. Как видишь RegExp - универсальнее
3. как я и сказал - тут главное уметь писать паттерны/шаблоны...
4. сравни длину своей функции и код от buchlotnik

P.S. buchlotnik - спасибо, не дадим в обиду RegExp)
Изменено: New - 13.03.2021 00:30:48
 
Цитата
New написал:
спасибо, не дадим в обиду RegExp)
во истину, брат  ;)
Соблюдение правил форума не освобождает от модераторского произвола
 
Для выделения руб
Код
Function iDigits(cell$)
Dim j As Integer
 With CreateObject("VBScript.RegExp")
     .Global = True
     .Pattern = "[\d ]+\.[\d]+(?= руб)"
   If .test(cell) Then
     Set iDigits = .Execute(cell)(0)
     iDigits = CDbl(Replace(Replace(iDigits, " ", ""), ".", ","))
   Else
     iDigits = ""
   End If
 End With
End Function

У buchlotnik универсальней
 
Kuzmich, спасибо..
тааак куда ТС ушёл? Марат, а ну вернись! )
 
Цитата
New написал:
первый вариант мне больше нравился...
он под десятичную запятую, а мало ли что у кого в системе; да и вообще писал в лоб - логику примера не сразу уловил, так что лучше удали, не учи ТС-а плохому... )))
Изменено: buchlotnik - 13.03.2021 00:28:48
Соблюдение правил форума не освобождает от модераторского произвола
 
ок, удалил
 
Цитата
и сравнение с RegExp
сравнивать RegExp с вашим макросом, это как водку сравнивать с пивом. очевидно, что водка гораздо эффективнее.
а если вот это:
Price 1 000 000.25 руб 2 500,325$ aed....1754-0025
записать так:
Price 1 000 000.25 руб 2 500,325$ aed....1754-0025 + 3руб или -47
3 или -47 это не числа? (судя по названию темы, пытаемся из текста извлечь числа))
Код
Function GetNum$(t, n)
  Dim re, ms, s$
  Set re = CreateObject("VBScript.RegExp"): re.Global = True
  re.Pattern = "(-*\d[0-9 ]*)(\D{0,1})(\d)*": Set ms = re.Execute(t)
  If ms.Count < n Then Exit Function Else Set ms = ms(n - 1)
  If IsEmpty(ms.Submatches(2)) Then s = ms.Submatches(0) _
  Else s = Replace(ms, ms.Submatches(1), Application.DecimalSeparator)
  GetNum = Replace(s, " ", "")
End Function
Изменено: Ігор Гончаренко - 13.03.2021 04:17:36
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
New, на самом деле, ответ уже был в функции RealNum (нужно было просто добавить нужные разделители). Просто  для проверки знаний форумчан...)
Да и в функции, взятой из https://www.planetaexcel.ru/techniques/7/4844 все подробно описано.

А функцию свою написал по мотивам макроса от ZVI - что то усложненно показалось... https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=8&TID=41673&am...
Изменено: Marat Ta - 13.03.2021 07:44:59
 
Цитата
Marat Ta написал:
Просто  для проверки знаний форумчан...)
это уже откровенный троллинг
Цитата
Marat Ta написал:
ответ уже был в функции RealNum (нужно было просто добавить нужные разделители)
ну-ка ну-ка - продемонстрируй как ту маску "просто" дополнить для этого конкретного примера?
Изменено: buchlotnik - 13.03.2021 09:13:15
Соблюдение правил форума не освобождает от модераторского произвола
 
Цитата
Marat Ta написал:
Просто  для проверки знаний форумчан...)
Пожалуйста, больше не создавай тем на форуме...
 
Было 2 бана. Сейчас третий - на 30 дней.

Marat Ta, если и после этого бана Вы не успокоитесь, учетка будет заблокирована.  Всех уже задолбал своим поведением...
 
хорошая новость))

теперь можно потестировать мою функцию и писать сюда, какое число не было извлечено из текста или было извлечено не правильно
т.е. выкладывать сюда текст, в котором произошла ошибка в работе функции
сразу хочу сказать что в тексте 1 2 3 4 5 будет извлечено ОДНО число 12345
спасибо
Изменено: Ігор Гончаренко - 13.03.2021 13:05:22
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Фишка ещё в том, что хоть регулярки и универсальнее, конкретную задачу функция  ТС-а решала быстрее почти в три раза, но что было в приоритете скорость или универсальность мы может быть узнаем через месяц, спасибо дядя модератор за наше счастливое детство ))))   :D
Соблюдение правил форума не освобождает от модераторского произвола
 
как раз за месяц автор темы возможно сможет заточить свою функцию до тех возможностей извлечения чисел из текста, которые уже работают в функции  из #15

да...Marat Ta уже не с нами, но тема его живет))
Изменено: Ігор Гончаренко - 13.03.2021 13:31:58
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
я думал Covid его остановил на время, оказывается БАН
 
Цитата
buchlotnik написал:
конкретную задачу функция  ТС-а решала быстрее почти в три раза
Привет, Михаил.
А у меня наоборот получилось - регулярки в два раза быстрее
Цитата

1,058594
0,53125
Скрытый текст
 
Андрей VG, согласен. Там мой косяк с
Код
CreateObject("VBScript.RegExp")

В таком варианте
Код
Function exec(t, n)
    If FReg Is Nothing Then
        Set FReg = New VBScript_RegExp_55.RegExp
        FReg.Global = True
    End If
    With FReg
        .Pattern = "([\d\s]+)([-\.,]+)(\d+)"
        Set s = .Execute(t)(n - 1)
    End With
    exec = CDec(s.SubMatches(0) & Application.DecimalSeparator & s.SubMatches(2))
End Function
и при небольшом допиле вашего кода:
Код
Public Function GetNumber(ByVal fromText As String, n) As Double
    If FReg Is Nothing Then
        Set FReg = New VBScript_RegExp_55.RegExp
        FReg.Global = True
    End If
    FReg.Pattern = "[\.\-]"
    fromText = FReg.Replace(fromText, ",")
    FReg.Pattern = "(?:\d+ ?)+,\d+"
    GetNumber = CDbl(FReg.Execute(fromText)(n - 1).Value)
End Function

имеем (столбцы - это номер вхождения)

два Replace быстрее Submatches, спасибо за науку  ;)
Изменено: buchlotnik - 14.03.2021 11:44:00
Соблюдение правил форума не освобождает от модераторского произвола
 
Андрей VG, buchlotnik, Ребзя, не увидел у вас объявления переменных, но…
…при Option Explicit и большом вызове RE-функций, я делаю так:
Попробуйте так - должно быть заметно быстрее при частом вызове функции в цикле
Про зверя VBScript_RegExp_55 и особенности в сравнении с "обычным" RegExp - не слышал  :)

Цитата
buchlotnik: Application.DecimalSeparator
надёжнее использовать Application.International(xlDecimalSeparator) или Mid$(1/2,2,1)и тоже в Static засунуть, чтобы не вычислять при каждом вызове (я так и не понял - вошло или нет в сборку, так что просто инфа)

Цитата
Андрей VG: IsDec(s)
я не понял, откуда эта функция, но, определённо, для русского уха прочесть вслух было забавно  :D

Цитата
Marat Ta: Просто  для проверки знаний форумчан...)
мда…
Изменено: Jack Famous - 15.03.2021 11:52:09
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Разница более 20 раз, но можно ещё выжать
Изменено: Jack Famous - 15.03.2021 17:47:53
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
Про зверя VBScript_RegExp_55
Всего лишь путь в пространстве имён :)  
Цитата
Jack Famous написал:
Разница в 20 раз, но можно ещё выжать
Ну, так никто и не отрицал, что две регулярки лучше чем одна :)
 
Цитата
Андрей VG: Всего лишь путь в пространстве имён
приветствую!
Не понимаю)) подключение "на лету"? У меня ошибка была с ней - я что-то делал не так?
Цитата
Андрей VG: никто и не отрицал, что две регулярки лучше чем одна
Основной буст именно статика даёт - обновил тест выше
Изменено: Jack Famous - 15.03.2021 17:49:37
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
del
Изменено: Jack Famous - 15.03.2021 17:48:59
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Страницы: 1 2 След.
Наверх