Что нового

[Данные, строки] Сортировка чисел по условию через регулярные выражения

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
ViktorSPB
Если проблема памяти то решать надо уже её. Можно читать файл частями по 50 Мб., после обработки сохранить первую партию в файл. Будет проблема обрезки, последняя строка каждого куска испортится. Ищем с конца первый перенос строки, отрезаем справа эту часть текста и прилепляем в начало следующего куска.

Думаю тут проблема будет уже в скорости, при выборе вариантов. Каждый вариант протестировать на скорость. Функция _StringRegExp от CreatoR у меня долго работала при запуске в цикле
Код:
$sPattern = "^[90-12147]$"

For $i = 90 To 12147
	$aRet = _StringRegExp($i, $sPattern, 3)
	If Not IsArray($aRet) Or Not ($aRet[0]==$i) Then MsgBox(0, 'Сообщение' & $i, $aRet[0]&' ???')
Next

И это всего 12 000 элементов, не 15 млн.
Построчный вариант тоже дольше чем одно регулярное выражение обрабатывающее 1 млн строк.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
IMHO сначала, нужно найти строки, опираясь на ценовой диапазон и литеру обозначающею покупку или продажу, и уже из полученного списка формировать строку заданного вида, как в этой теме "Найти строку по условию и преобразовать эту строку"
Если я правильно понял задачу.
 
Автор
V

ViktorSPB

Новичок
Сообщения
109
Репутация
0
Garrett, AZJIO, спасибо за помощь.

Построчный вариант тоже дольше чем одно регулярное выражение обрабатывающее 1 млн строк.
AZJIO, правильно я Вас понял, что регулярное выражение работает быстрее? Если так, то я в правильном направлении пошел. Если, конечно, вообще правильно такие задачи решать с помощью AutoIt. Другими инструментами вообще не владею, а AutoIt очень и очень помогает, лучшего пока не встречал для своих задач.

Наверное самый главный вопрос: Самый ли быстрый и эффективный способ обработки строк - регулярные выражения? А то сейчас голову сломаю и себе и у других людей время отниму, и в итоге прийду к такой же производительности как при обычном переборе..

Что касается памяти - да, так и думал, читать блок байт, парсить, выяснять остаток обрезанных данных, следующий блок читать с позиции последней минус остаток. Пока я до этого не дошел, но гипотетически вижу так.

Garrett, я намеренно не прояснял всю задачу, потому что ветка получилась бы специфическая и с темой "вот что надо сделать". Поэтому я представил что мне нужно и блоками решаю задачу сам и прошу помощи у вашего сообщества. Стараюсь, чтобы темы мои и еще кому-либо оказались полезными.

Секрета нет в том, что я хочу сделать, в двух словах объясню почему я именно так поставил вопрос.
Есть файл или группа файлов с данными вида, который я указал. Это может быть очень большой файл. например запросто 20-50 млн.строк. Или в разы больше.
Файл/ы используется как хранилище, данные в него/них дописываются.
Возникает задача обработать данные определенного временного диапазона, нужного инструмента ( в моем примере задача упрощена, основное хранилище уже отпарсено по одному инструменту).
1) надо вытащить данные согласно времени и инструменту. Перебирать такое кол-во строк... Я так и сделал, это самое простое и, конечно, прежде чем писать на форум я проделал эту работу, посмотрел что получилось по времени и только тогда обратился сюда.
2) Нужно определить независимо от направления сделки максимумы и минимумы цен. Эту задачу я пока рег. выражениями не решал.

Вот даже на этом этапе возникает условие: дата/время от и до. Уже тут мне надо прописать алгоритм сродни тому, что ищу в этой ветке.

3) После определения максимумов и минимумов я расчитываю шаг.
4) И наконец с этим шагом вытаскиваю и обрабатываю все покупки и продажи.

Я так и сделал, читал построчно файл, находил дату, дальше раскидавал по другим файлам-temp данные по признаку S или B. Потом эти файлы обрабатывал.

Но пришла мысль, что если разобраться с рег. выражениями и суметь их тут правильно применить, я смогу перешагнуть некоторые этапы прграммы и сходу практически получать что нужно. Без переборов особых, без лишних обращений и т.д.

Пока я вижу задачу - сформировать патерн. Чтоб делал то, что я описал в предыдущем посте. Может, если у вас есть другое видение, поделитесь, пожалуйста.
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
ViktorSPB
Сколько времени сейчас обрабатывается файл?

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

Если использовать 2 регулярных выражения из прошлой темы, мне не понравилось то, что сначала переставляются строки, допустим их 3 из 50 млн. Далее извлекаем строки, опять просматривая 50 млн. Не проще ли сначала извлечь нужные строки, а потом их переставлять (уже только 3)? Но тут проблема - приходится использовать вторую переменную. При соединении строки нужно выделить память для ещё столько же сколько объединённые строки. А если читать допустимыми частями, то можно значительно ускорить обработку не получив ошибку о недостаточности памяти.

Вот инициализация 50 000 000 вызовов 154 сек (2,5 мин), а наверняка без компиляции патерна движком, просто возврат ошибки.
Код:
$timer = TimerInit()
For $i = 1 To 50000000
	StringRegExpReplace('', '', '')
Next
MsgBox(0, "Время выполнения", 'Время : ' & Round(TimerDiff($timer) / 1000, 2) & ' сек')
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
ViktorSPB
Что касается паттернов для поиска диапазонов. Вот некоторые которые могут тебе помочь разобраться:

Числа от 0 до 255 ^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$
Числа от 0 до 999 ^([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$
Числа от 1 до 999 ^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$
Число 0 или 00 до 59 ^[0-5]?[0-9]$
Число 0 или 000..366 ^(0?[0-9]?[0-9]|[1-2][0-9][0-9]|3[0-6][0-9]|36[0-6])$
Число 0 или 000..127 ^(0?[0-9]?[0-9]|1[0-1][0-9]|12[0-7])$
Я думаю нужно делать функцию которая будет возвращать паттерн под определенные условия. (Минимальное - максимальное значения для поиска).
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
inververs [?]
нужно делать функцию которая будет возвращать паттерн под определенные условия.
Согласен.
Но это будет не из простых задач, я тут посидел пол часа, и у меня уже мозг вскипел :stars:.
Думаю алгоритм примерно такой:

Код:
;Числа от 0 до 255 ^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$
;Числа от 0 до 999 ^([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$
;Числа от 1 до 999 ^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$

$vTest = '[0-255]'

$iStart = 0
$iEnd = 255
$iLen = StringLen($iEnd)

$sRet = ''

For $i = 1 To $iLen
	;Собираем шаблон в зависимости от длины и концовки текущего числа
	$iMid = StringMid($iEnd, $i, 1)
	
	$sRet &= $iMid & '|'
	
	For $j = $iStart To $iMid
		$sRet &= $j & '|'
	Next
	
	;Далее видимо нужно как то заменять промежуточные числа на шаблоны...
Next

ConsoleWrite($sRet & @LF)
 
Автор
V

ViktorSPB

Новичок
Сообщения
109
Репутация
0
Только сумел добраться до темы. Сейчас все опробую и отпишусь с результатами.
Спасибо.

Да, я пошел по предложенному пути.
Для это предлагаю скрипт, чтобы работать с одними и теми же вх. данными:
Код:
#include <Array.au3>

Dim $sS = '7'&@CRLF&'45'&@CRLF&'245'&@CRLF&'254'&@CRLF&'2'&@CRLF&'21'&@CRLF&'25'&@CRLF&'jkl'&@CRLF&'36'&@CRLF&'3'&@CRLF&'33'&@CRLF

MsgBox(0,'',$sS)

Dim $aArray = StringRegExp($sS,'(*ANYCRLF)(?m)^(\d+)$',3)
;Dim $aArray = StringRegExp($sS,'(?=((*ANYCRLF)(?m)^(\d)$)\S+',3)
_ArrayDisplay($aArray)


Этот скрипт выводит все числа.
Теперь я работаю над тем, чтобы патерн выдал значения при УСЛОВИИ, что в обработке только одна цифра.
Я нашел в описании Условные подмаски и Атомарную группировку.
Разбираюсь с ними, трудновато для меня.. Сможете мне помочь в данном случае выделить только одноцифровые значения?
Тут вариант с простой заменой \d+ на \d не подойдет, нужно именно условием в патерне прописать, дальше я буду его расширять.
Есть более опытные люди по работе с условными подмасками?

вот нашел вариант
Код:
(*ANYCRLF)(?m)(?=^(\d)$)\d+

По моей логике патерн работает так - Если с начала строки одна цифра, то её и берем. d+ в конце сделал для проверки, чтобы быть увернным, что не захватятся лишние значения. В итоге и без \d+ выдается в результате что нашлось.
:stars: это я наверное такой недалекий, но понять логику, если, конечно она есть в рег. выражениях для меня та еще задача.. Столько часов потрачено и так мало продвинулся в понимании с помощью и уроков и книжку уже скачал...

Сделал вариант с проверкой на диапазон от 1 до 44.
Код:
Dim $sS = '7'&@CRLF&'45'&@CRLF&'245'&@CRLF&'254'&@CRLF&'2'&@CRLF&'21'&@CRLF&'25'&@CRLF&'jkl'&@CRLF&'36'&@CRLF&'3'&@CRLF&'33'&@CRLF

MsgBox(0,'',$sS)

;Dim $aArray = StringRegExp($sS,'(*ANYCRLF)(?m)^(\d+)$',3)
Dim $aArray = StringRegExp($sS,'(*ANYCRLF)(?m)(?=^([1-9])$)|(?=^([1-3][0-9])$)|(?=^([4][0-4])$)',3)
_ArrayDisplay($aArray)


Объясните мне, пожалуйста, почему массив на выходе с пустыми значениями?
Что там RegExp такого находит соответствующего моему патерну? Как избавиться от пустот корректировкой патерна? :wall_brake:
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
ViktorSPB [?]
выделить только одноцифровые значения
Одноцифровые пожалуйста: ^[0-9]$ :smile:

почему массив на выходе с пустыми значениями?
(*ANYCRLF) -Это вообще что такое? что вы хотели этим найти. Если это директива, то в PCRE вроде такой нету.
(?=^([1-9])$)|(?=^([1-3][0-9])$)|(?=^([4][0-4])$) - тут вообще не указано, что именно искать. Вы только определили позиции для поиска. Потому что "Positive и Negative Lookahead" сами по себе не производят поиск, а используются что бы уточнять условия.

Если что то не работает - посмотрите, что возвращает @error после функции StringRegExp ;)



Добавлено:
Сообщение автоматически объединено:

И изначально вы выбрали какой то тяжелый способ для выборки текста, но весьма интересный, мне самому интересно как вы решите свой вопрос. :smile: Т.к самому писать функцию по составлению паттернов еще не доводилось.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
ViktorSPB
Я не пойму зачем всё усложнять, если задача в первом сообщении изложена корректно, то чем не подходит моё решение?
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
ViktorSPB [?]
Сделал вариант с проверкой на диапазон от 1 до 44.

Паттерн будет такой:
(?m)^([1-9]|[1-3][0-9]|4[0-4])$


Добавлено:
Сообщение автоматически объединено:

CreatoR
Может человек хочет разобраться в регулярных выражениях? Конечно, если бы я решал, то все данные переписал бы в базу данных и достал нужные значения одним запросом :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
inververs [?]
Может человек хочет разобраться в регулярных выражениях?
Для этого есть FAQ и другие справочники, а данная тема специфическая.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Да, специфическая, согласен. Но если человек в конце напишет функцию для составляния паттернов поиска диапазона чисел, то она будет очень полезная.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
inververs [?]
если человек в конце напишет функцию для составляния паттернов поиска диапазона чисел, то она будет очень полезная
Будет полезная, но автор темы совсем не в том направлении, он так будет долго подбирать шаблоны :laugh:.

Нужно найти алгоритм составления шаблона (см. мой последний код в теме), а это совсем не просто, imho.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
CreatoR [?]
Нужно найти алгоритм составления шаблона (см. мой последний код в теме), а это совсем не просто, imho.
Может быть проведете конкурс по данной теме?? :smile: :beer:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Последний оффтоп удалён, нарушителям предупреждение в профиль.

inververs [?]
Может быть проведете конкурс по данной теме?
Да, и как я буду проводить конкурс когда у самого нет решения задачи? Как то не серъёзно :laugh:.
 
Автор
V

ViktorSPB

Новичок
Сообщения
109
Репутация
0
Добрый день! Завалило меня текучкой не заняться вопросом нормально..

inververs,
по поводу (*ANYCRLF) тут нашел http://autoit-script.ru/index.php/topic,37.0.html

Что касается алгоритма да, так и надо. Но я иду понятным для меня путем. Я хочу сначала ручками все вбить и получить правильный результат. Поймите правильно, я плохо разбираюсь в рег. выражениях. Вот в том примере я хотел на выходе увидеть массив из совпадений. Увидел массив с верными числами, но и еще с пустыми строками. То есть совпадений, напрмер, 7, а строк в массиве 11, 4 строки пустые. Не знаю, что там еще может быть нашлось, или я не правильно формулу написал, не учел чего-то.. Мои мысли по этому вопросу я в посте изложил. Но понял что да, буду разбираться сам.
Наверное трудно вам поверить, что на такую простую задачу для начала формирования простейшего патерна я потратил несколько часов подряд (более 4-х точно).. И результата нужного пока не достиг. Как чуть-чуть освобожусь, сразу примусь за решение. Вопрос по-прежнему актуален.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
ViktorSPB [?]
Наверное трудно вам поверить, что на такую простую задачу для начала формирования простейшего патерна я потратил несколько часов подряд
Не трудно, т.к это совсем не простая задача, и я это уже писал.

Продублирую вопрос:
[?]
Я не пойму зачем всё усложнять, если задача в первом сообщении изложена корректно, то чем не подходит моё решение?
:scratch:
 
Верх