:: Visual Foxpro, Foxpro for DOS
Дубли и сортировка чисел в символьной строке
dfr
Автор

Сообщений: 254
Откуда: Барнаул
Дата регистрации: 29.07.2005
Нужно убрать дубли и упорядочить по возрастанию числа в текстовой последовательности.
Например из '21,22,22,23,40,27,40,5' сделать '5,21,22,23,27,40'

Пока сделал на скорую руку:

lcIn = '21,22,22,23,40,27,40,5'
lcOut = ''
CREATE CURSOR c1 (s1 i)
FOR lnI = 1 TO OCCURS(',',lcIn) + 1
INSERT INTO c1 VALUES ( VAL(GETWORDNUM(lcIn,lnI,',')) )
ENDFOR
SELECT c1
INDEX on s1 TAG s1 UNIQUE
SCAN
lcOut = lcOut + TRANSFORM(c1.s1) + ','
ENDSCAN
lcOut = LEFT(lcOut,LEN(lcOut)-1)
*MESSAGEBOX(lcIn + CHR(13) + lcOut)

Но нужно прогонять этот скрипт по множеству строк в таблицах, может есть решение "по быстрее"?
Или в этом что оптимизировать?
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
Taran

Сообщений: 13623
Откуда: Красноярск
Дата регистрации: 16.01.2008
Через массив делай.
Alines... Asort.
И между этими командами пробежаться по массиву и строки преобразовать в int.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
Давно нашел, думаю здесь, и использую.
Например № дока может быть a123пп, и это надо отсортировать.
В общем, думаю вполне для вашей задачи то.
**************************************************
*** Функция, возвращающая текст для сортировки ***
*** Цифры дополняются нулями до заданной длины ***
*** Автор - Игорь Ильин, ''.phorum_html_encode('mars2215@mail.ru').'' ***
**************************************************
#DEFINE PAD_LENGTH 6
#DEFINE PAD_CHAR "0"
#DEFINE DIGIT_DUMMY "0"
#DEFINE DIGITS '0123456789'
#DEFINE DUMMIES Replicate( DIGIT_DUMMY, Len(DIGITS) )
*** 1-й параметр - исходный текст для сортировки.
*** 2-й параметр, необязательный - длина результата. Может быть числом, либо логическим .T. Во втором случае длина результата будет равна длине исходного текста.
*** 3-й параметр, необязательный - длина, до которой цифры дополняются ведущими нулями. Если ничего не передавать, то будет использована константа PAD_LENGTH.
Lparameters tcName, tuReturnLength, tnPad_Length
Local lcReturnName, lcDummyName, lnTextLen, lnTextStart, lnDigitStart, lnPad_Length
*SET STEP ON
*** Уточняем, до какой длины нужно дополнять цифры
lnPad_Length = Iif(Vartype(tnPad_Length) = "N", tnPad_Length, PAD_LENGTH)
*** заменяем цифры на "пустышки"
lcDummyName = Chrtran( Rtrim(tcName), DIGITS, DUMMIES )
lcReturnName = ''
lnTextStart = 1 && начало текстового блока
lnTextLen = At( DIGIT_DUMMY, lcDummyName ) - 1 && длина текстового блока
DO while lnTextLen >= 0
*** Сохраняем блок букв
lcReturnName = lcReturnName + Substr(tcName, lnTextStart, lnTextLen)
lnDigitStart = lnTextStart + lnTextLen
*** ->
*** Добавляем пробел перед блоком цифр (эмпирически найденное правило)
If lnDigitStart>1 and Right(lcReturnName,1) # " "
lcReturnName = lcReturnName + " "
EndIf
*** ->
*** ищем конец блока цифр (спасибо Роману Кольцову за уточнения в коде)
lnTextStart = lnDigitStart + 1
DO while Substr(lcDummyName, lnTextStart, 1) == DIGIT_DUMMY
lnTextStart = lnTextStart + 1
EndDo
*** если начались буквы, сохраняем блок цифр
lcReturnName = lcReturnName + Padl(Substr(tcName, lnDigitStart, lnTextStart - lnDigitStart), lnPad_Length, PAD_CHAR )
lnTextLen = At(DIGIT_DUMMY, Substr(lcDummyName, lnTextStart) ) - 1
EndDo
lcReturnName = lcReturnName + Substr(tcName, lnTextStart)
*** Если необходимо, меняем длину результата
DO Case
Case Vartype(tuReturnLength)="N"
lcReturnName = Padr(lcReturnName, tuReturnLength)
Case Vartype(tuReturnLength)#"L"
Wait window "2-й параметр SortName() имеет тип " + Vartype(tuReturnLength) + Chr(13) + ;
"Возможны только параметры типа N или L" nowait
Case tuReturnLength = .T.
lcReturnName = Padr(lcReturnName, Len(tcName))
EndCase
Return lcReturnName


------------------
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
dfr
Автор

Сообщений: 254
Откуда: Барнаул
Дата регистрации: 29.07.2005
Taran
Через массив делай.
Alines... Asort.
И между этими командами пробежаться по массиву и строки преобразовать в int.

А уникальные как там искать? (дубли убирать)
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
Дмитрий Петров

Сообщений: 3066
Откуда: Пермь
Дата регистрации: 09.07.2001
Что то я фокс совсем забыл
lcInput = "21,22,22,23,40,27,40,5"
lnNumRows = ALINES(laValues,lcInput,1+4,",")
DIMENSION laValues[lnNumRows ,1]
CREATE CURSOR tmp( vValue C(50))
APPEND FROM ARRAY laValues
SELECT distin ALLTRIM(vValue) as exp1 FROM tmp ORDER BY 1 ASC INTO CURSOR q1
SELECT q1
lcOut =""
SCAN
lcOut = lcOut + allt(exp1) + ','
ENDSCAN
lcOut = LEFT(lcOut,LEN(lcOut)-1)
?lcOut
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
Может, так подойдет:
tcIn = '21,22,22,23,40,27,40,5'
lcIn = ','+tcIn+','
lcOut = ','
FOR i = 1 TO 100
lcI = TRANSFORM(i)
IF ','+lcI+','$lcIn AND !','+lcI+','$lcOut
lcOut = lcOut + lcI + ','
ENDIF
ENDFOR
lcOut = SUBSTR(lcOut,2,LEN(lcOut)-2)
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
pasha_usue

Сообщений: 3647
Откуда: Е-бург
Дата регистрации: 06.10.2006
lulgu
lcOut = SUBSTR(lcOut,2,LEN(lcOut)-2)
Здесь будет ошибка, если IF не сработает ни разу.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
pasha_usue
lulgu
lcOut = SUBSTR(lcOut,2,LEN(lcOut)-2)
Здесь будет ошибка, если IF не сработает ни разу.

Странно, но IF срабатывает.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
pasha_usue
Здесь будет ошибка, если IF не сработает ни разу.

Ошибки не будет, будет пустая строка.

tcIn = '121,122,122,123,140,127,140,105'
tcIn = ''
tcIn = '21, 22, 40'
...

Дмитрий Петров
CREATE CURSOR tmp( vValue C(50))
Наверное всё же (vValue I) - если требуется числовая сортировка а не строковая (когда 5 стоит после 40) - ну и в выводе transform()/ltrim(str()) применить...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
Igor Korolyov
Ошибки не будет, будет пустая строка.

tcIn = '121,122,122,123,140,127,140,105'
tcIn = ''
tcIn = '21, 22, 40'

С чего вы так решили?
Эти ваши цифры я вижу впервые - для примера взята строка от ТС, новых требований он пока не предъявлял.

Раз уж этот цикл вызвал затруднения, проверьте свои цифры (предварительно подправьте свою третью строку через CHRTRAN()).

LPARAMETERS tcIn
IF GETWORDCOUNT(tcIn,',') <= 1
RETURN tcIn
ENDIF
LOCAL lcIn,lcOut,i,lcI
lcIn = ','+tcIn+','
lcOut = ','
FOR i = MIN(&tcIn) TO MAX(&tcIn)
lcI = TRANSFORM(i)
IF ','+lcI+','$lcIn AND !','+lcI+','$lcOut
lcOut = lcOut + lcI + ','
ENDIF
ENDFOR
RETURN SUBSTR(lcOut,2,LEN(lcOut)-2)
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
LUCIAN

Сообщений: 343
Откуда: Лида Беларусь
Дата регистрации: 25.03.2008
CRLF=CHR(13) + CHR(10)
SET SAFETY OFF
SELECT 0
CREATE CURSOR CSRT (ZNAC C(10))
SELECT 0
CREATE CURSOR CTEST (STROKA C(240))
INSERT INTO CTEST VALUE ('21,22,22,23,40,27,40,5')
INSERT INTO CTEST VALUE ('121,122,122,123,140,127,140,105')
SCAN
=STRTOFILE(STRTRAN(CTEST.STROKA,',',CRLF),'CRAB.TXT')
SELECT CSRT
ZAP
APPEND FROM CRAB.TXT DELIMITED WITH BLANK
SELECT LTRIM(ZNAC) ZNAC FROM (SELECT DISTINCT PADL(RTRIM(ZNAC),10) ZNAC FROM CSRT ORDER BY 1) CSRT1 INTO CURSOR CSRT READWRITE
COPY TO CRAB.TXT DELIMITED WITH ','
SELECT CTEST
REPLACE CTEST.STROKA WITH STRTRAN(CHRTRAN(FILETOSTR('CRAB.TXT'),',',''),CRLF,',')
ENDSCAN
BROW



Исправлено 2 раз(а). Последнее : LUCIAN, 09.10.18 14:10
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
pasha_usue

Сообщений: 3647
Откуда: Е-бург
Дата регистрации: 06.10.2006
Igor Korolyov
Ошибки не будет, будет пустая строка.
Да, не будет. Значит, придирку с отрицательными аргументами SUBSTR не засчитываем. Просто не очень красиво.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
pasha_usue
Igor Korolyov
Ошибки не будет, будет пустая строка.
Да, не будет. Значит, придирку с отрицательными аргументами SUBSTR не засчитываем. Просто не очень красиво.

Странные вы с ИК.
Вы в цикл от 1 до 100 вставляете цифры за пределами этого диапазона и удивляетесь, что не вставляется.
Вроде не новички.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
pasha_usue

Сообщений: 3647
Откуда: Е-бург
Дата регистрации: 06.10.2006
lulgu
Вроде не новички.
В этом и проблема. Анализ граничных значений производится в голове, автоматом. Другой вопрос, что я уже не помню, будет Exception в фоксе, или нет.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
pasha_usue
Да, не будет. Значит, придирку с отрицательными аргументами SUBSTR не засчитываем. Просто не очень красиво.

Обдолбанность данного решения отсутствие формальной ошибки не отменяет...

2 LUCIAN
Плачу кровавыми слезами. На кой чёрт в простой задаче столько ненужных действий, включая двойное создание текстового файла?
При том что основа "логики" такая же как в решении Дмитрия Петрова чуть выше...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
LUCIAN

Сообщений: 343
Откуда: Лида Беларусь
Дата регистрации: 25.03.2008
Igor Korolyov
Плачу кровавыми слезами
Тогда,метод пузырька,которого полно в интернете,теперь слёзы пойдут кровавыми пузырями
SELECT 0
CREATE CURSOR CTEST (STROKA C(240))
INSERT INTO CTEST VALUE ('21,22,22,23,40,27,40,5')
INSERT INTO CTEST VALUE ('121,122,122,123,140,127,140,105')
SCAN
DIMENSION msort(1)
n=ALINES(msort,CTEST.stroka,1+4+8,',')
m=n
for i = 1 to n - 1
for j = 1 to n - i
if PADL(msort[j],10) = PADL(msort[j + 1],10) AND msort[j] <> '9999999999'
=ADEL(msort,j + 1)
msort[n]='9999999999'
m=m-1
J=J-1
LOOP
endif
if PADL(msort[j],10) > PADL(msort[j + 1],10)
k = msort[j]
msort[j] = msort[j + 1]
msort[j + 1] = k
endif
endfor
ENDFOR
m.stroka=''
FOR i=1 TO m
m.stroka=m.stroka+msort(i)+IIF(i=m,'',',')
endfor
REPLACE CTEST.STROKA WITH m.stroka
ENDSCAN
BROW



Исправлено 3 раз(а). Последнее : LUCIAN, 15.10.18 08:38
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
pasha_usue

Сообщений: 3647
Откуда: Е-бург
Дата регистрации: 06.10.2006
LUCIAN
Тогда,метод пузырька,которого полно в интернете,теперь слёзы пойдут кровавыми пузырями
Вот же время у кого-то свободного много.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
akvvohinc

Сообщений: 4201
Откуда: Москва
Дата регистрации: 11.11.2008
lulgu
Может, так подойдет:
Проблема приведенного алгоритма именно в том, что он может подойти, а может и не подойти. Или даже хуже - сегодня он подошел, а завтра, на новых данных, перестанет работать - в условии ничего не пишется о том, числа какой величины могут быть в этой последовательности.

ТС делает упор на скорость обработки, а именно с ней и могут быть проблемы - выполнять миллион проверок пусть даже для 100 в среднем чисел в строке, явно нерационально.

Но может быть, среднее количество чисел в строке огромно - тогда алгоритм может и устроить, но его минус - необходимость указания конкретного максимума - кто знает, какие данные придут завтра. Хуже всего, что прога отработает, не выполнив задачи, но пользователь об этом не узнает, если только случайно не заметит, что числа 101 в выходной строке больше нет.
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
akvvohinc
lulgu
Может, так подойдет:
Проблема приведенного алгоритма именно в том, что он может подойти, а может и не подойти. Или даже хуже - сегодня он подошел, а завтра, на новых данных, перестанет работать - в условии ничего не пишется о том, числа какой величины могут быть в этой последовательности.

ТС делает упор на скорость обработки, а именно с ней и могут быть проблемы - выполнять миллион проверок пусть даже для 100 в среднем чисел в строке, явно нерационально.

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

Про число 100 я уже отвечал.
Для других чисел выложил расширенное решение с MIN/MAX, что даже сам ИК признал, что он от него обдолбался.
На скорость проверять чьи-то миллионные записи у меня нет времени, да я и не навязываю свое решение никому.
Если кому-то пригодится, то и хорошо.



Исправлено 1 раз(а). Последнее : lulgu, 10.10.18 17:03
Ratings: 0 negative/0 positive
Re: Дубли и сортировка чисел в символьной строке
akvvohinc

Сообщений: 4201
Откуда: Москва
Дата регистрации: 11.11.2008
lulgu
Для других чисел выложил расширенное решение с MIN/MAX

Функции MIN и MAX имеют ограничение на 26 параметров, так что они не могут ничего гарантировать.

lulgu
На скорость проверять чьи-то миллионные записи у меня нет времени

Не записи миллионные, я имел в виду, что в строке могут встретиться любые числа, например, 1458761.

А так - свою задачу ТС решил и сам.
Он просил помочь как раз с точки зрения скорости работы алгоритма.



Исправлено 1 раз(а). Последнее : akvvohinc, 10.10.18 22:36
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 27 Владимир Максимов  (Гостей: 26)

© 2000-2024 Fox Club 
Яндекс.Метрика