:: Visual Foxpro, Foxpro for DOS
Сортировка в случайном порядке
Dron2003
Автор

Сообщений: 81
Дата регистрации: 14.11.2008
Всем привет!
Ребята, натолкните на мысль. Есть таблица 20 записей, надо вывести эти записи в форму в случайном порядке, причем, в следующий раз опять их все перемешать. Пробовал через генератор случайного числа в диапазоне от 1 до 20, то получается хорошо для вывода 10-13 записей. А если вывести все 20, что процесс формирования затягивался на 20-30 минут. Да, надо чтобы те записи которые уже выведены на экран больше не выводились. Т.е. нужна сортировка в случайном порядке.
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Приложи программку, которая 20 минут выводит 20 записей...
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
Dron2003
Автор

Сообщений: 81
Дата регистрации: 14.11.2008
Ну, примерно так:
SELECT 2
ZAP
RAND(-1)
voprMax = 20 &&
voprMin = 1 &&
FOR n=1 to zach_kol1
DO WHILE .t.
tmp_bilet1=INT((voprMax - voprMin + 1) * RAND() + voprMin)
IF AT(STR(tmp_bilet1),zach_str)=0
zach_str=zach_str+' '+STR(tmp_bilet1)
EXIT
ENDIF
ENDDO
SELECT 2
INSERT INTO exzamen select * from bilet where n_bil=tmp_bilet1 .and. n_vopr=13
ENDFOR
Wait clear
SELECT 2



Исправлено 1 раз(а). Последнее : Dron2003, 31.01.18 10:27
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
ry

Сообщений: 2113
Дата регистрации: 24.09.2007
Например, использовать курсор с дополнительным полем, которое заполнить случайными числами, затем вывести отсортированный по этому полю курсор.
Что-то вроде
select 0.000 as randfield, * from bilet into cursor temp readwrite
select temp
scan
replace randfield with rand() && в цикле, а не через replace for или update, чтобы каждой записи присваивался свой rand()
endscan
select * from temp order by randfield into cursor examen
Код не проверял, это как идея. Кстати, а какая версия FoxPro?



Исправлено 3 раз(а). Последнее : ry, 31.01.18 10:47
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
Dron2003
Автор

Сообщений: 81
Дата регистрации: 14.11.2008
Беда в том, что генератор случайного числа очень часто повторяет одну и туже цифру.
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Занимательный код... Преобразовал, чтобы можно пробовать:
CLEAR
zach_kol1 = 20
zach_str = ""
RAND(-1)
voprMax = 20 &&
voprMin = 1 &&
FOR n=1 to zach_kol1
DO WHILE .t. && выходить по ESC !
tmp_bilet1=INT((voprMax - voprMin + 1) * RAND() + voprMin)
IF AT(STR(tmp_bilet1),zach_str)=0
zach_str=zach_str+' '+STR(tmp_bilet1)
EXIT
ENDIF
ENDDO
? tmp_bilet1 && INSERT INTO exzamen select * from bilet where n_bil=tmp_bilet1 .and. n_vopr=13
ENDFOR
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
Dron2003
Автор

Сообщений: 81
Дата регистрации: 14.11.2008
я его выдернул из модуля где выборка идет 20 вопросов из 40 билетов. Работает очень быстро, но если выбирать из 20 билетов... то зависнуть может надолго.
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Вот так можно получить неповторяющийся случайный набор чисел в нужном диапазоне
CLEAR
voprMax = 20 &&
voprMin = 1 &&
RELEASE A
DIMENSION A[1]
RAND(-1)
m.i = 0
FOR m.n=voprMin TO voprMax
m.i = m.i+1
DIMENSION A[m.i, 2]
A[m.i, 1] = m.n && генерируем нужные выходные неповторяющиеся числа
A[m.i, 2] = RAND()
ENDFOR
=ASORT(A, 2) && собственно "перемешивание" по случайному числу RAND() во 2м столбце
FOR m.i=1 TO ALEN(A,1)
? A[m.i,1] && посмотреть результат перемешивания
ENDFOR
Ratings: 0 negative/1 positive
Re: Сортировка в случайном порядке
Dron2003
Автор

Сообщений: 81
Дата регистрации: 14.11.2008
Супер! Спасибо!
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
ry
Например, использовать курсор с дополнительным полем, которое заполнить случайными числами, затем вывести отсортированный по этому полю курсор.
Что-то вроде
Гораздо проще:
SELECT bilet.*, RAND() rnd FROM bilet ORDER BY rnd
Если нужно выбирать "20 из 40", то просто добавить в запрос TOP 20.

Всё прочее - это горе от ума (и потому г*нокод ).


------------------
WBR, Igor
Ratings: 0 negative/1 positive
Re: Сортировка в случайном порядке
ry

Сообщений: 2113
Дата регистрации: 24.09.2007
Да, легко и красиво, а я чего-то засомневался в том, как поведет себя rand() в запросах. Крайне редко пользовался этой функцией.
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
leonid

Сообщений: 3204
Откуда: Рига
Дата регистрации: 03.02.2006
ry
а я чего-то засомневался в том, как поведет себя rand() в запросах.

И, между прочим, небезосновательно. При использовании rand() в запросах порой получаются странные результаты. Вот, например:

clear
create cursor tmp1 (f1 i)
for i = 1 to 100
insert into tmp1 values (0)
next
rand(-1)
for i = 1 to 10
select * from tmp1 where rand() < 0.5 into cursor tmp2
?reccount()
next

P.S. Так как написал Игорь, конечно же писать можно.
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Да, вероятно в этом случае фокс ошибочно полагает RAND() за детерминированную функцию после первого вычисления выражения, и далее уже не вычисляет его.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
leonid

Сообщений: 3204
Откуда: Рига
Дата регистрации: 03.02.2006
Igor Korolyov
Да, вероятно в этом случае фокс ошибочно полагает RAND() за детерминированную функцию после первого вычисления выражения, и далее уже не вычисляет его.

Ну, как видно из примера, он не вычисляет ее только в том случае, если при первом прогоне rand() выдала значение меньше 0.5. В противном случае вполне себе вычисляет.
Ratings: 0 negative/0 positive
Re: Сортировка в случайном порядке
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Ну так если на первом прогоне WHERE даёт .F. то ошибочно приняв функцию за детерминированную можно тупо "выйти из цикла" - не делать более ни одного теста. А уж если там .T. то приходится делать остальные прогоны - и там уже фокс вынужден постоянно вычислять WHERE выражение. Полноценной поддержки детерминированных функций (равно как и просто средств указать что некоторая функция таки "чистая") в фоксе нет, увы.
Кстати, фоксу достаточно легко можно указать на "недетерминированность" выражения. Самое простое: rand()+f1 < 0.5+f1 или даже совсем уж "глупое" rand()+f1-f1 < 0.5 - и уже никаких "предположений" он не делает - честно считает каждый раз. Ну или завернуть RAND() в свою UDF - даже однострочную с RETURN RAND() - и тоже он уже не помышляет про такого рода "оптимизацию"


------------------
WBR, Igor
Ratings: 0 negative/0 positive


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

On-line: 20 (Гостей: 20)

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