Пару-тройку дней назад присутствовал при дискуссии goraph и Ajenta насчёт структур данных QSP. Под впечатлением от слов goraph, что ограничения работы с массивами, мешают написать настоящее текстовое RPG, набросал модуль работы с таблицами.
Данный модуль предоставляет следующие возможности:
Текущая версия: 1.3.1 (скачать)
Документация on-line: https://ifiction.ru/h/otg_lib_tables_help.html
Пример работы с таблицей:
GS 'Таб.Создать','Персонажи','Имя, Здоровье, Раса' GS 'Таб.СоздатьИндекс','Персонажи','Имя' GS 'Таб.ДобавитьСтроку','Персонажи','Крокодил',90,'Варвар' GS 'Таб.ДобавитьСтроку','Персонажи','Арабелла',77,'Амазонка' GS 'Таб.ДобавитьСтроку','Персонажи','Адельм',60,'Монах' GS 'Таб.ДобавитьСтроку','Персонажи','Каннибал',75,'Варвар' GS 'Таб.ДобавитьСтроку','Персонажи','Марина',77,'Амазонка' GS 'Таб.Сортировать', 'Персонажи', 'Раса,Здоровье-' GS 'Таб.Установить','Персонажи','Адельм','Здоровье',25 GS 'Таб.Выбрать','Персонажи','Раса','=','Варвар' :перебор_строк_таблицы if func('Таб.Следующая','Персонажи','Герой'): *NL func('Таб.Значение','Персонажи','Номер строки')+'. '+$Герой['Имя']+' ('+Герой['Здоровье']+')' JUMP 'перебор_строк_таблицы' end GS 'Таб.Удалить','Персонажи'
Неактивен
Обновил модуль: добавил в архив документацию, почистил код, реализовал некоторые новшества.
Неактивен
Обновил модуль:
Выложил документацию на сайт.
Неактивен
В архив добавил вариант модуля с англоязычными названиями операторов и функций. Внёс эту информацию в документацию.
Неактивен
Версия 1.2 (скачать):
Добавил в модуль команду "Таб.Сортировать". Теперь строки таблицы можно сортировать как по одной, так и по нескольким колонкам по возрастанию и убыванию.
GS 'Таб.Сортировать', 'Персонажи', 'Раса, Здоровье-'
Неактивен
Хотел сказать спасибо за модули, использовал модуль с меню, очень удобно. По поводу этого модуля возник такой вопрос про элемент "Номер строки":
Если использовать Table.Select, то похоже нумерация строк сбивается
Например:
gs 'Table.Create', 'Test', 'Name, Number'
gs 'Table.NewLine', 'Test', 'Abc',1
gs 'Table.NewLine', 'Test', 'Abc',2
gs 'Table.NewLine', 'Test', 'Qwe',1
gs 'Table.NewLine', 'Test', 'Qwe',2
GS 'Table.Select','Test','Name','=','Qwe'
if func('Table.Next','Test'): LineNum=func('Table.Value','Test','Номер строки')
В этом случае в LineNum будет 1, а не 3. Если же вызвать строку c LineNum позже(например DeleteLine), то будет вызвана строка 'Abc',1, а не 'Qwe',1
Так задуманно? Проблема еще в том, что если создать численный индекс(1,2,3...), то функции типа GetValue интерпретируют цифровой параметр как номер строки, а не значение индексного поля, даже если я определил индекс. Плюс к тому, если стирать строки, то нумерация строк пересчитывается.
Есть ли какой-то простой способ установить каждой строке уникальный цифровой номер(типа autonumber), чтобы потом по нему можно было ссылаться, даже если часть строк трешь?
Еще в справке пропущено описание Table.LinesCount
Отредактировано Билли Бонс (02.09.2014 05:28)
Неактивен
Билли Бонс написал:
По поводу этого модуля возник такой вопрос про элемент "Номер строки":
Если использовать Table.Select, то похоже нумерация строк сбивается
Так задуманно?
Есть ли какой-то простой способ установить каждой строке уникальный цифровой номер(типа autonumber), чтобы потом по нему можно было ссылаться, даже если часть строк трешь?
Да, так задумано. "Номер строки" возвращает порядковый номер строки. В твоём примере — в выборке. В принципе, без проблем можно добавить параметр "ID строки", который будет возвращать уникальный ID строки во всей таблице (благо, он такой есть), который не изменяется никогда, типа: func('Table.Value','Test','ID строки')
.
Правильно я понимаю, что ты хочешь иметь возможность использовать уникальный ID строки вместо номера строки во всех функциях, где номер строки является одним из параметров (типа GetValue из твоего вопроса)?
Билли Бонс написал:
Проблема еще в том, что если создать численный индекс(1,2,3...), то функции типа GetValue интерпретируют цифровой параметр как номер строки, а не значение индексного поля, даже если я определил индекс.
Проблему понял. Да, числовые значения воспринимаются как номер строки, а не значение индекса. Тут нужно подумать, как сделать лучше. Как вариант, для числовых значений индекса его можно указывать строкой: "index:3": func('Table.GetValue','Test','index:2','Name')
. А для уникального ID строки так: func('Table.GetValue','Test','id:3','Name')
.
Билли Бонс написал:
Если же вызвать строку c LineNum позже(например DeleteLine), то будет вызвана строка 'Abc',1, а не 'Qwe',1
Можно пример кода?
Неактивен
Olegus t.Gl. написал:
Можно пример кода?
Например:
gs 'Table.Create', 'Test', 'Name, Number'
gs 'Table.NewLine', 'Test', 'Abc',1
gs 'Table.NewLine', 'Test', 'Abc',2
gs 'Table.NewLine', 'Test', 'Qwe',1
gs 'Table.NewLine', 'Test', 'Qwe',2
GS 'Table.Select','Test','Name','=','Qwe'
if func('Table.Next','Test'):
LineNum=func('Table.Value','Test','Номер строки')
func('Table.GetValue','Test',LineNum,'Name')
end
Выдает 'Abc', a не 'Qwe', как можно было бы ожидать. Если func('Table.GetValue','Test',LineNum,'Name') вызывается дальше по коду - результат тот же самый.
Olegus t.Gl. написал:
Правильно я понимаю, что ты хочешь иметь возможность использовать уникальный ID строки вместо номера строки во всех функциях, где номер строки является одним из параметров (типа GetValue из твоего вопроса)?
Да. В принципе, я добился того, чего хотел и имеющимися средствами (через FindValue), однако отсутствие id мне показалось нелогичным. Номер строки часто сбивается, и показывает вовсе не на ту строку, которую ожидаешь.
Olegus t.Gl. написал:
Проблему понял. Да, числовые значения воспринимаются как номер строки, а не значение индекса. Тут нужно подумать, как сделать лучше. Как вариант, для числовых значений индекса его можно указывать строкой: "index:3":
func('Table.GetValue','Test','index:2','Name')
. А для уникального ID строки так:func('Table.GetValue','Test','id:3','Name')
.
Да, как вариант.
Неактивен
Билли Бонс написал:
Olegus t.Gl. написал:
Можно пример кода?
Например:
gs 'Table.Create', 'Test', 'Name, Number'
gs 'Table.NewLine', 'Test', 'Abc',1
gs 'Table.NewLine', 'Test', 'Abc',2
gs 'Table.NewLine', 'Test', 'Qwe',1
gs 'Table.NewLine', 'Test', 'Qwe',2
GS 'Table.Select','Test','Name','=','Qwe'
if func('Table.Next','Test'):
LineNum=func('Table.Value','Test','Номер строки')
func('Table.GetValue','Test',LineNum,'Name')
end
Выдает 'Abc', a не 'Qwe', как можно было бы ожидать. Если func('Table.GetValue','Test',LineNum,'Name') вызывается дальше по коду - результат тот же самый.
Ясно. 'Table.GetValue' работает с абсолютным порядковым номером строки во всей таблице. А в LineNum у тебя хранится относительный порядковый номер из выборки. При работе с выборкой нет средств указания конкретной строки именно из выборки — там все действия реализуются через перебор и относятся к текущей строке.
Полагаю, добавлением сущности уникального ID подобные проблемы можно будет снять.
На этой неделе сделаю.
Неактивен
Билли Бонс написал:
Еще в справке пропущено описание Table.LinesCount
Информация о функции "Table.LinesCount" справке была, но из-за ошибки в теге заголовка она "сливалась" с описанием предыдущей функции. Поправил тег, теперь всё хорошо: https://ifiction.ru/h/otg_lib_tables_he … LinesCount
Неактивен
Доработки сделал, внесу правки в документацию — выложу.
Неактивен
Спасибо
Неактивен
Olegus t.Gl. написал:
Доработки сделал, внесу правки в документацию — выложу.
Добрался до документации. Выложил обновлённый модуль (1.3):
Неактивен
Не удается добавить строку больше 8-и элементов
gs 'Table.NewLine', 'test', 1, 2, 3, 4, 5, 6, 7, 8 - все норм
Добавляешь 9-й элемент - Неверное число аргументов оператора / функции!
Неактивен
testament написал:
Не удается добавить строку больше 8-и элементов
gs 'Table.NewLine', 'test', 1, 2, 3, 4, 5, 6, 7, 8 - все норм
Добавляешь 9-й элемент - Неверное число аргументов оператора / функции!
Это ограничение самой платформы QSP. Обсуждается тут.
Неактивен
Такой вопрос:
Функция Таб.{IDСтроки}
Вместо
if isnum($ARGS[14]):
Result=func('Таб.{IDСтроки}',$ARGS[0],val($ARGS[14]))
EXIT
end
Не должно ли быть вот так:
if isnum($ARGS[14]):
Result=val($ARGS[14])
EXIT
end
Если я правильно понял код, то в первом варианте функция путает номер строки и id и в результате глючит
Неактивен
Билли Бонс написал:
Такой вопрос:
Функция Таб.{IDСтроки}
ВместоКод:
if isnum($ARGS[14]): Result=func('Таб.{IDСтроки}',$ARGS[0],val($ARGS[14])) EXIT endНе должно ли быть вот так:
Код:
if isnum($ARGS[14]): Result=val($ARGS[14]) EXIT endЕсли я правильно понял код, то в первом варианте функция путает номер строки и id и в результате глючит
Нет, всё правильно. Все функции, в которых есть обращение к номеру строки, работают с абсолютным номером строки в таблице. Он же взят за ID. Поэтому функция при обращении по ID обращается по абсолютному номеру строки.
Однако, в данном модуле при удалении строки происходит сдвиг номеров строк — я не во всех своих решениях так делал именно для сохранения индексов — поэтому могут быть глюки, да. Так что мой косяк. Тут нужно подумать, как реорганизовать данные, чтобы такого не происходило. В принципе, это не особо сложно.
Неактивен
Я делал следующую проверку:
gs 'Table.Create', 'Test', 'Name'
gs 'Table.NewLine', 'Test', 'A'
gs 'Table.NewLine', 'Test', 'B'
gs 'Table.NewLine', 'Test', 'C'
gs 'Table.NewLine', 'Test', 'D'
gs 'Table.NewLine', 'Test', 'E'
gs 'Table.NewLine', 'Test', 'F'
gs 'Table.DeleteLine', 'Test','id:1'
gs 'Table.DeleteLine', 'Test','id:3'
gs 'Table.DeleteLine', 'Test','id:4'
'By id:'+func('Table.GetValue','Test','id:5','Name')
'By num:'+func('Table.GetValue','Test',2,'Name')
В варианте
if isnum($ARGS[14]):
Result=val($ARGS[14])
EXIT
end
я получал
By Id:E
By Num:E
В варианте
if isnum($ARGS[14]):
Result=func('Таб.{IDСтроки}',$ARGS[0],val($ARGS[14]))
EXIT
end
Я получал
By Id:
By Num:C
По логике должно быть Е, у нее id=5 и она становится второй строкой после стирания 3 строк из начала таблицы
Неактивен
Билли Бонс написал:
По логике должно быть Е, у нее id=5 и она становится второй строкой после стирания 3 строк из начала таблицы
Ну так я и говорю, что проблемы проявляются после удаления строк. Поправлю.
Неактивен
Ошибка с определением уникального идентификатора строки исправлена. Выложена версия 1.3.1.
Неактивен
Спасибо. Если не сложно, то какие процедуры изменились? Я у себя менял только код Таб.{IDСтроки}, как в сообщении 17. Вроде все тогда заработало. Что-то еще исправленно?
Неактивен
Билли Бонс написал:
Спасибо. Если не сложно, то какие процедуры изменились? Я у себя менял только код Таб.{IDСтроки}, как в сообщении 17. Вроде все тогда заработало. Что-то еще исправленно?
Только эта функция и изменена.
Неактивен
Сделал еще одно изменение:
В модуле Table.Copy убрал строку
copyarr 'otg_Таблица_<<$ARGS[1]>>_Выборка', 'otg_Таблица_<<$ARGS[0]>>_Выборка'
а строку
copyarr 'otg_Таблица_<<$ARGS[1]>>_ТекущаяСтрока', 'otg_Таблица_<<$ARGS[0]>>_ТекущаяСтрока'
заменил на
dynamic "otg_Таблица_<<$ARGS[1]>>_ТекущаяСтрока=0"
Причина: если в таблице Source есть данные, но при копировании используется фильтр под который не подходит ни одна из строк, то таргет-таблица пустая, а вот ее выборка не пустая. Причем она не сбрасывается командой Table.Select, так как та сбрасывает выборку только если количество строк больше 0. В результате команды Table.Next и Table.Value по пустой таблице дают ненулевые результаты.
На всякие случай еще в Table.Select добавил после 5 строки
killvar 'otg_Таблица_<<$ARGS[0]>>_Выборка'
dynamic "otg_Таблица_<<$ARGS[0]>>_ТекущаяСтрока=0"
чтобы выборка сбрасывалась и если таблица пуста, так как возможно какте-то еще процедуры могут создать непустую выборку в пустой таблице
После исправления вроде все заработало
Отредактировано Билли Бонс (01.02.2015 21:11)
Неактивен
Билли Бонс написал:
После исправления вроде все заработало
А что именно не работало?
Неактивен
Ну я описал выше. Пример:
gs 'Table.Create', 'Test', 'Name'
gs 'Table.NewLine', 'Test', 'A'
gs 'Table.NewLine', 'Test', 'B'
gs 'Table.NewLine', 'Test', 'C'
gs 'Table.Select', 'Test'
gs 'Table.Copy', 'Test', 'TestTarget','Name','=','Z'
gs 'Table.Select','TestTarget'
'Next Res='+func('Table.Next','TestTarget')
'Value Res='+func('Table.Value','TestTarget','ID строки')
Выдает
Next Res=-1
Value Res=1
После исправления
Next Res=0
Value Res=
Что и должно быть, так как таблица пуста. Проблема была в том, что не обнулялся массив "Выборка" как я описал выше.
Неактивен