On-line: Andrey, PSP, tnsr2, гостей 2. Всего: 5 [подробнее..]
АвторСообщение
администратор




Пост N: 2792
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.03.13 17:35. Заголовок: Ascan ?


 
Есть массив вида {{},{},{}}

поиск веду в первом элементе
do while !eof()
..
if ascan(klnmas[1],{|fff| fff==nakl_r1->kod_kl})==0
skip
loop
endif
.......
skip
enddo
медленновато что то или меня уже плющит....
есть какой то другой аналог Ascan который пошустрее работает ?
Понятно что вот так быстрее будет
if ascan(klnmas[1],nakl_r1->kod_k)==0
skip
loop
endif


RDD скипает быстрее чем работает Ascan с блоком кода....


Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 44 , стр: 1 2 3 All [только новые]


Администратор




Пост N: 2764
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 18.03.13 20:10. Заголовок: Поиск в ascan выполн..


Поиск в ascan выполняется методом полного перебора массива, так что это медленный поиск. С использованием блока кода он будет еще медленнее, но и без блока кода медленно. Особенно в большом массиве. Особенно в цикле.
Насчет того, чем заменить: у меня этих ascan'ов хоть пруд пруди. Вкратце их алгоритм: надо при заполнении массива сразу его сортировать, и использовать быстрый поиск в отсортированном массиве.
Но точно так же работает хэш, так что может быть стоит использовать вместо моих нестандартных функций стандартные средства харбора для работы с хэш.

Если я правильно понял твою задачу, ты формируешь двумерный массив с размерностями 3*n, где в первом подмассиве хранятся ключи, а в двух следующих - соответствующие им данные.
Если "перевернуть" массив, т.е. использовать размерности не 3*n, а n*3, то можно будет использовать хэш, примерно как в примере Петра:

http://clipper.borda.ru/?1-4-0-00000784-000-0-0-1354477086

только можно вместо

_AADD(hDim,{495, 1})

вызывать

_AADD(hDim,{495, x1, x2, ...})

т.е. варьировать 2-ю размерность

Ну а свою функцию я когда-то давно выкладывал в теме:

https://groups.google.com/forum/#!topicsearchin/comp.lang.xharbour/sorted$20array/comp.lang.xharbour/b0jKrNhcNAk

в этой же теме Пшемек рассказывает, как использовать хеш


Спасибо: 0 
ПрофильЦитата Ответить



Не зарегистрирован
Зарегистрирован: 01.01.70
ссылка на сообщение  Отправлено: 18.03.13 21:43. Заголовок: Неполный поиск сокращает время


В этой задаче можно завершать поиск , если хотя бы один элемент найден,
как делает ASCAN2() (см. ниже) в отличие от ASCAN(), который все равно проверяет весь массив.

Function ascan2(arr,bl, nstart, nqu )
Local n:=0,m,L:=len(arr),nret:=0,nend
Local lbl:= ( valtype(bl)="B")
if nstart=NIL
nstart=1
endif
if nqu=NIL
nend:=L
else
nend:=nstart-1+nqu
endif
for n=nstart to nend
if lbl
if eval(bl,arr[n])
nret :=n
EXIT
endif
else
if bl==arr[n]
nret :=n
EXIT
endif
endif//lbl
next i
return nret


Спасибо: 0 
Цитата Ответить
Администратор




Пост N: 2765
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 18.03.13 21:52. Заголовок: petr707 пишет: как ..


petr707 пишет:

 цитата:
как делает ASCAN2() (см. ниже) в отличие от ASCAN(), который все равно проверяет весь массив.



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

вот фрагмент этой функции для поиска строки в массиве:

            else if( HB_IS_STRING( pValue ) ) 
{
do
{
PHB_ITEM pItem = pBaseArray->pItems + nStart++;

/* NOTE: The order of the pItem and pValue parameters passed to
hb_itemStrCmp() is significant, please don't change it. [vszakats] */
if( HB_IS_STRING( pItem ) && hb_itemStrCmp( pItem, pValue, fExact ) == 0 )
return nStart;
}
while( --nCount > 0 );
}


Поиск в этой функции реализован самым оптимальным образом. Но это не делает оптимальным сам алгоритм полного перебора.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2793
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.03.13 22:01. Заголовок: Pasha Спасибо за по..


Pasha
Спасибо за подробный ответ !

Pasha пишет:

 цитата:
Если я правильно понял твою задачу, ты формируешь двумерный массив с размерностями 3*n, где в первом подмассиве хранятся ключи, а в двух следующих - соответствующие им данные.



Ну не совсем так.
Изначально создается массив amas:={{},{},{}} c 3 элементами
где каждый элемент массив.
Затем я обрабатываю справочник контрагентов на предмет условий
заданных юзером и заполняю первый элемент кодами контрагентов.
Остальные 2 элемента так же заполняются соответствующими
цифирками.
После этого я обрабатываю журнал накладных , предварительно
установив в нем SCOPE за интервал дат (по индексу типа DTOS(data_n))
и хожу в цикле проверяя массив (отсеивая не нужных контрагентов).
Вот и все.
Думаю сортировка массива скорости не прибавит так же как и работа с хэш.
По любому этот отчет в Harbour cтроится в разы быстрее нежели в
Clipper+SIX или Clipper+ADS.
Просто хотелось еще не много ускорить ;)


Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 2766
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 18.03.13 22:36. Заголовок: Dima пишет: Думаю с..


Dima пишет:

 цитата:
Думаю сортировка массива скорости не прибавит так же как и работа с хэш.



Для небольших массивов разница будет несущественной, а для больших - просто огромной. Вот к примеру такой тест:

func main
Local nSize := 10000, nI, nKey, nSec, nRes
Local aDim := {}, aDim2 := {}
Local hDim := { => }

// заполнение массива и хеша
for nI := 1 to nSize
nKey := ((nI + Int(nSize/2)) % nSize) + 1
AADD(aDim, nKey)
AADD(aDim2, nI)
_AADD(hDim, nKey, nI)
next

nRes := 0
? 'Array scan', len(aDim)
nSec := Seconds()
for nI := 1 to nSize
nRes += aDim2[ASCAN(aDim, nI)]
next
? (Seconds() - nSec)*1000, nRes

nRes := 0
? 'Hash scan', len(aDim)
nSec := Seconds()
for nI := 1 to nSize
nRes += hDim[nI]
next
? (Seconds() - nSec)*1000, nRes

return nil

PROCEDURE _AADD( aHash, nKey, nI )

aHash[nKey] := nI

retu

Размер nSize я взял 10000, чтобы время хоть как-то отличалось от нуля. Результат выводится в миллисекундах. Для массива у меня получилось 219 мс, для хеша - опять ноль.
Если nSize задать 30000, то результат для массива будет 1953 мс, для хеша - 15мс. Разница в производительности выходит на порядки.
Это все равно, что сравнивать разницу поиска с помощью skip и seek. Кстати, аналогия получается прямая, поскольку алгоритмы поиска при этом совершенно идентичны.


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2795
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.03.13 23:24. Заголовок: Pasha Буду мозговат..


Pasha
Буду мозговать , спасибо.

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 89
Зарегистрирован: 19.05.05
ссылка на сообщение  Отправлено: 19.03.13 09:24. Заголовок: Я может не знаю всех..


Я может не знаю всех дополнительных условий, но для приведенного выше алгоритма почему
нельзя сделать индекс <Имя контрагента>+dtos (data) в журнале накладных . Для каждого
кантрагента,попадающего под условия, отбираются данные за указанный интервал. В этом случае
отпадает перебор по ascan () и отсекаются лишние движения по базе накладных.


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2796
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 19.03.13 10:46. Заголовок: Что то как то не при..


Что то как то не привычны эти Hash и пока что потерялся ;)
Как следующий код преобразовать к Hash массивам ?

 
ams:={{},{},{}}

for i=1 to 100
aadd(ams[1], i )
aadd(ams[2],seconds())
aadd(ams[3],time())
next

i:=ascan(ams[1],33)

? ams[1][ i ]
? ams[2][ i ]
? ams[3][ i ]



Вот так что ли .....
 
local ams:={=>}
local npos

for i=1 to 100
ams[ i ]:={seconds(),time()}
next

if HB_HHASKEY( ams, 33, @nPos )
? hb_hget(ams,npos)[1]
? hb_hget(ams,npos)[2]
endif




Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 166
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 19.03.13 12:08. Заголовок: Dima пишет:Что то ка..


Dima пишет:
 цитата:
Что то как то не привычны эти Hash и пока что потерялся


Может поможет: Скрытый текст


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2797
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 19.03.13 12:31. Заголовок: SergKis Спасибо. М..


SergKis
Спасибо.

Мне вот не понятна одна штука

 
aHash := {10=>, 20=>}
? HB_HHASKEY( aHash, 5, @nPos ), nPos // .F. 0
? HB_HHASKEY( aHash, 10, @nPos ), nPos // .T. 1
? HB_HHASKEY( aHash, 15, @nPos ), nPos // .F. 1 // почему не ноль ?
? HB_HHASKEY( aHash, 20, @nPos ), nPos // .T. 2
? HB_HHASKEY( aHash, 25, @nPos ), nPos // .F. 2 // почему не ноль ?



Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2798
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 19.03.13 14:01. Заголовок: В общем в первом при..


В общем в первом приближении разобрался. Всем спасибо !

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 167
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 19.03.13 16:56. Заголовок: SergKis пишет:Может ..


SergKis пишет:
 цитата:
Может поможет:


Небольшой пример вдогонку:Скрытый текст


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2812
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.03.13 13:01. Заголовок: еще тест ;) proc m..


еще тест ;)

 
proc main
local nfor:=1000000
local i
local ms:={}
local hms:={=>}
local nsec

nsec:=seconds()
for i=1 to nfor
aadd(ms,i)
next
? (seconds()-nsec)*1000 //641

nsec:=seconds()
for i=1 to nfor
hms:=i
next
? (seconds()-nsec)*1000 //36937 но если предварительно сделать (до заполнения массива)
// hb_hAllocate( hms, nfor ) , тогда время 821



nsec:=seconds()
ascan(ms,nfor)
? (seconds()-nsec)*1000 //31

nsec:=seconds()
HB_HHASKEY(hms,nfor)
? (seconds()-nsec)*1000 //0


return


Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 2768
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.03.13 13:27. Заголовок: Конечно, при использ..


Конечно, при использовании хеша добавление в него происходит медленнее, чем при добавлении элемента в массив.
Это тоже самое, что добавлять записи в файл с индексом медленнее, чем в файл без индекса, так как в первом случае еще обновляется индекс. Выигрыш достигается затем при поиске по ключу.
Еще к тому же AADD оптимизирован по выделению памяти, т.е. элементы в него добавляются не по одному. Хеш без такой оптимизации сильно ему проиграет. То, что настолько сильно, для меня сюрприз.


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2813
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.03.13 13:34. Заголовок: Есть такая функция a..


Есть такая функция
aValues := hb_hValues( aHash ) Возвращает массив всех значений массива aHash
А нет ли похожей которая возвращает массив значений с определенным ключиком ?

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 2769
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.03.13 13:54. Заголовок: Dima пишет: А нет л..


Dima пишет:

 цитата:
А нет ли похожей которая возвращает массив значений с определенным ключиком ?



Так в хеш ключ может быть только в одном экземпляре. И значение может быть одно.
Или надо выбрать массив по диапазону ключей ?


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2814
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.03.13 13:56. Заголовок: Pasha пишет: Или на..


Pasha пишет:

 цитата:
Или надо выбрать массив по диапазону ключей ?


Да. Я не так выразился.

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 2770
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.03.13 14:04. Заголовок: Нет, увы, такой функ..


Нет, увы, такой функции нет

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2815
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.03.13 14:07. Заголовок: Еще вопросец ;) fm..


Еще вопросец ;)

 
fmas:={}
hmas:={=>}

dbeval({|| hmas[recno()]:={kod_kl,kmcod,codn}})


fmas:=xxxx()
как быстро заполнить массив fmas значениями ключей
для kmcod==3 ?



BM_DBSETFILTERARRAY(fmas)


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2816
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.03.13 14:21. Заголовок: Пока посетила только..


Пока посетила только вот такая идея
 
use klient new
hb_hAllocate( hmas, lastrec() )
dbeval({|| hmas[recno()]:={kmcod,codgr}})
// для kmcod==3

hb_hEval( hmas, {|key,sval,ind| if(sval[1]==3,aadd(fmas,key),)})
// при размере массива 700000 записей hb_hEval работает 530 мс , хочется что то побыстрее


BM_DBSETFILTERARRAY(fmas)
dbgotop()
browse()



Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 44 , стр: 1 2 3 All [только новые]
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 256
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет