Пытаюсь постичь глубокий смысл этой функции. Но, что-то не получается. Примеры, приведенные в руководстве, содержат функции обратного вызова с
Код
function fn(t)
if t.qty == 103 then
или
Код
function fn(par1, par2, par3)
if par1 == 103 and par2 == “SPBFUT” and par3 == “RIM3” then
Это что же, для каждой конкретной выборки свою функцию писать !?
Хотелось бы иметь универсальную fn, а набор контролируемых параметров и их значения задавать при вызове SearchItems.
В принципе, я написал такую функцию, function SearchTables(tables,s,e,fn,...). Работает с переменным списком аргументов, а универсальная fn(t,...) выбирает таблицы, удовлетворяющие ВСЕМ условиям, например:
Код
st = SearchTables("trades",0,getNumberOf("trades")-1,fn,"price",119.35,"qty",10)
Но она использует getItem(), а как я понимаю, именно из-за слишком медленной ее работы и была создана SearchItems ...
если работаете с колбеками, то эта функция нужна лишь при запуске скрипта для выборки того, что уже принято, если оно Вам надо. ---------------------------- А при запуске скорости особо и не надо. ------------------------ Поэтому нет особой разницы каким образом выбрать уже принятые данные .
"Никто не мешает в fn передавать какие нибудь параметры."
Дело даже не в значениях параметров. В приведенных примерах fn - принципиально различные функции. Одна принимает таблицу и проверяет один конкретный параметр, другая получает и проверяет три параметра.
Например, вот такая универсальная функция получает произвольное число параметров (пар имя, значение) и проверяет то, что ВСЕ они для заданной таблицы удовлетворены.
Код
function fn(t,...)
local arg = {...}
for k,v in ipairs(arg) do
if k % 2 == 1 then
key = v
else
val = v
if t[key] ~= val then
return false
end
end
end
return true
end
универсальное медленнее специального. ------------------ Вам что надо? Быстро или универсально (т е лень писать код) ? -----------------------------------
В данном случае замедления не будет, а удобство налицо - fn один раз приводится для любых проверок/выборок с любым набором параметров. А раз все равно getItem используется, то такой подход дает максимальное удобство при сохранении скорости. Конечно, если понадобится другой тип выборки (например qty > 1 and qty < 10) то придется отдельную функцию писать.
Андрей 77 написал: В данном случае замедления не будет, а удобство налицо - fn один раз приводится для любых проверок/выборок с любым набором параметров. А раз все равно getItem используется, то такой подход дает максимальное удобство при сохранении скорости. Конечно, если понадобится другой тип выборки (например qty > 1 and qty < 10) то придется отдельную функцию писать.
Добрый день. А не могли бы Вы привести законченный пример с использованием этой универсальной функции поиска?
--
-- SearshTables
--
--
-- Универсальная функция обратного вызова для SearchTables.
-- Реализует проверку условий для переменного набора параметров
-- Возвращает true если удовлетворены ВСЕ условия (AND), иначе - false
--
function fn(t,...)
local arg = {...}
for k,v in ipairs(arg) do
if k % 2 == 1 then
key = v
else
val = v
if t[key] ~= val then
return false
end
end
end
return true
end
--
-- Функция поиска элементов (таблиц) удовлетворяющих набору критериев.
-- Переменное число параметров и соответствующих значенией, например :
--
-- SearchTables("trades",0,getNumberOf("trades")-1,fn,"seccode","SBER","qty",1,"price",120)
--
-- Возвращает таблицу, сожержащую сделки (таблицы) по SBER с qty=1 И price=120.
function SearchTables(tables,s,e,fn,...)
local f = {},k
local arg = {...}
k = 0
for n = s,e do
local t = getItem(tables,n)
if fn(t,...) then
k = k+1
table.insert(f,k,t)
end
end
return f
end
--
-- Пример использования SearchTables
--
function main()
st = SearchTables("trades",0,getNumberOf("trades")-1,fn,"seccode","SRM6","price",12138,"qty",1)
message("Found trades: "..#st,1)
end
Основные затраты при поиске перебором используя getItem это передача структур данных из хост-программы через стек в скрипт. SearchItems дает возможность уменьшить эти расходы. Используя Ваш пример я написал похожую реализацию с помощью функции SearchItems. Исходный код я немного модифицировал для подсчета статистики. Исходный пример Пример реализации с SearchItems Результаты тестов на моей машине:
Это все замечательно, но не меняет того странного обстоятельства, что вызов функции SearchItems не предполагает передачу значений параметров. Вместо написания конкретной функции fn для каждой выборки вы предлагаете использовать громоздкую новую функцию, вся задача которой - передавать значения параметров в SearchItems.
Проблема в самой реализации SearchItems. Очевидно, все определяется тем, как SearchItems вызывает fn. Нельзя ли дополнить ее таким образом, чтобы можно было передавать параметры и их значения в самой SearchItems ? Либо в виде последовательности параметров и значений (как в моем примере) либо в виде единой строки "par1=val1,par2=val2".
Michael Bulychev написал: Основные затраты при поиске перебором используя getItem это передача структур данных из хост-программы через стек в скрипт. SearchItems дает возможность уменьшить эти расходы. Используя Ваш пример я написал похожую реализацию с помощью функции SearchItems. Исходный код я немного модифицировал для подсчета статистики. Исходный пример Пример реализации с SearchItems Результаты тестов на моей машине:
Добрый день, Михаил Просьба протестите еще SearchItems без всех этих приблуд. Просто для конкретного варианта. Сколько будет по сравнению с этими выкрутасами. Спасибо ------------------------------------------------ Универсальная система (программа) - это такая система(программа) , разработчики которой не имеют ни малейшего представления о том, как реально ее будут применять.
Еще один вариант. Суть та же, но чуть попроще, чем у Михаила (я минималист :)). По сути - одна дополнительная универсальная функция, 17 строк. Работает так же, даже чуть быстрее (на 2%), правда у меня ПК в 4 раза медленнее, чем у Михаила :(
Код
-- SelectItems
-- Возвращает таблицу с номерами элементов в 'tables', удовлетворяющих
-- набору критериев вида p = { par1=val1, par2=val2, ... }
-- s - start, e - end
--
function SelectItems(tables,s,e,p)
local t,fields={},""
for key,val in pairs(p) do
fields = fields .. "," .. tostring(key)
t[#t+1] = val
end
local function fn(...)
local args = {...}
for key,val in ipairs(args) do
if t[key] ~= val then
return false
end
end
return true
end
return SearchItems(tables,s,e,fn,fields)
end
-- ---------------------------------------------------------------------
-- Пример использования SelectItems
-- ---------------------------------------------------------------------
function main()
local table,n,N,params
table = "all_trades"
n = getNumberOf(table)-1
params = {sec_code='RIM6',class_code='SPBFUT',qty=1}
N = 100
message("Selecting from "..table.." ("..n..") "..N.." times")
_start = os.clock()
for i = 1, N do
st = SelectItems(table,0,n,params)
end
_end = os.clock()
time = _end - _start
message("Found: "..#st..",time: "..string.format("%.1f",time),1)
end
Добрый день, Считаю, что возврат только номеров найденных строк не совсем удачное решение. После этого надо еще вытаскивать эти строки из хранилища. -------------------------------- Предлагаю возвращать таблицу номеров и таблицу самих строк, в которых возвращать лишь параметры, которые не участвовали в поиске. Спасибо
например, надо найти все активные стоп-заявки, чтобы их удалить. Указываем , что вернуть надо order_num, а ищем по flags. В результате получаем таблицу номеров активных стоп-заявок.
Michael Bulychev написал: Добрый день. Вы можете прямо в теле функции сохранять нужную вам информацию и всегда возвращать false.
но тогда какой смысл в возврате функцией таблицы номеров строк? Если следовать Вашей логике, то можно все сохранять в теле функции. И вообще все писать от печки.
Sergey Gorokhov написал: Никто не мешает задавать набор контролируемых параметров в функции SearchItems
Непонятно. Приведите пример.
В функции SearchItems последним параметром Вы задаете список параметров которые следует смотреть в функции fn. Пример есть в документации QLUA.chm:
Код
function fn(par1, par2, par3)
if par1 == 103 and par2 == "SPBFUT" and par3 == "RIM3" then
return true
else
return false
end
end
t1 = SearchItems("all_trades", 0, getNumberOf("all_trades")-1, fn, [B]"qty,class_code, sec_code"[/B])
Ирина написал: Но хотелось бы записи в виде таблицы с параметрами что ли, как в функции sendTransaction.
согласно документации, если последний параметр в функции SearchItems не задан то в функцию передается таблица со всеми параметрами. пример
Код
t1 = SearchItems ("all_trades",0,getNumberOf ("all_trades")-1, function(T) if (T.qty == 103) and (T.class_code== "SPBFUT") and (T.sec_code== "RIM3") then return true else return false end end)
Индекс конечного элемента, заданный переменной или функцией, вычисляется 1 раз перед поиском, или его изменение во время работы SearchItems будет учтено? Например, в SearchItems("all_trades", 0, getNumberOf("all_trades")-1, fn).
Откуда можно узнать, как индексируется таблица, возвращаемая SearchItems?
Ирина написал: Индекс конечного элемента, заданный переменной или функцией, вычисляется 1 раз перед поиском, или его изменение во время работы SearchItems будет учтено?
Один раз перед поиском.
Цитата
Ирина написал: Откуда можно узнать, как индексируется таблица, возвращаемая SearchItems?
Данные индексируются ровно в том порядке как поступили с биржи.
Цитата
Ирина написал: И ещё. Последовательность перебора элементов от стартового до конечного соблюдается или в хаотичном порядке?
Sergey Gorokhov написал: Данные индексируются ровно в том порядке как поступили с биржи.
Это Вы о расположении найденных элементов, видимо. Я интересуюсь, как индексируется таблица, созданная SearchItems? Нагуглила уже, что числами, начиная с 1. Но где это указано?
Sergey Gorokhov написал: Не понятно какого ответа Вы ожидаете.
Ну раз уж не ссылки на документацию, то хотя бы подтверждения, может, нюансов каких-то, т.к. информацию я нашла в неофициальном источнике... Но Ваш ответ лучше - смешнее!
Если я не ошибаюсь, раньше SearchItems ("all_trades",0,getNumberOf ("all_trades")-1) обрабатывал строки с "0" до последней. Сейчас только одну. Может я чего не так делаю?
Серега написал: Если я не ошибаюсь, раньше SearchItems ("all_trades",0,getNumberOf ("all_trades")-1) обрабатывал строки с "0" до последней.
У Вас в функции не хватает параметров, в частности функции обратного вызова.
Да, это понятно. Для примера:
Код
function fn(seccode,flags,qty)
if seccode=="SiH9" then
message ( tostring(qty) ) -- выдает только строку =0, а должен все строки
message ( tostring(flags) )
message ( tostring(seccode) )
end
end
function main()
SearchItems("orders", 0, getNumberOf("orders")-1, fn, "sec_code,flags,qty")
end
Да, в любом коде, берет только первую строку. (Напишите свой пример, чтобы долго не придираться. А то сейчас растянем) А раньше брал с 0 строки по последнюю строку в таблице. Те LUA, которые раньше с SearchItems работали, теперь обрабатывают этой функцией только первую заданную ("0" нулевую) строку. QUIK 7.24.1.15
fn – функция обратного вызова, возвращающая одно из следующих значений: true – текущий индекс учитывается в результате; false – текущий индекс не учитывается в результате; nil – поиск прерывается, функция SearchItems возвращает таблицу с индексами, найденными ранее, включая текущий индекс.
у Вас в коде, функция fn ничего не возвращает, т.е. по сути это nil, поэтому поиск и прекращается. Добавьте return true и поиск будет происходить по полному циклу
Парни, подскажите пожалуйста! Как через SearchItems, можно запомнить первую активную заявку в таблице "orders". И в следующий раз начинать с этой строки?
SearchItems (с 0 по end) в 5й строке активная заявка SearchItems (с 5 по end) в 10й строке активная заявка SearchItems (с 10 по end)
Sergey Gorokhov написал: Просто запомнить номер строки и в следующий раз указать его в SearchItems. не понятно в чем сложность
Тоже не понимаю в чем, но сложность остается. ))
Код
function fn(flags,order_num)
i=i+1
if bit.band(flags, 1)==1 then
message ( "активна "..tostring(i).." "..tostring(order_num))
-- return i
end
return true
end
function main()
is_run,i = true,0
while is_run do
SearchItems("orders", i, getNumberOf("orders")-1, fn, "flags,order_num")
message ( "последняя "..tostring( i ))
sleep(2000)
end
end
function OnStop(s)
is_run = false
end
Серега написал: Как запомнить строку с первой активной заявкой ?
1) записать order_num в глобальную переменную 2) записать в файл 3) записать в базу 4) записать в таблицу и т.п.
Поправка, надо не так. В fn не передается номер строки. Надо при нахождении нужной заявки делать return nil далее последняя запись в таблице которую возвращает SearchItems надо смотреть последнюю строку, она и будет содержать нужный номер строки