Здесь показаны различия между двумя версиями данной страницы.
Both sides previous revision Предыдущая версия Следущая версия | Предыдущая версия | ||
help:arrays [2014/12/02 16:46] asv ====Массив переменных==== |
help:arrays [2025/04/19 06:41] (текущий) aleks_versus [Функции и операторы для работы с массивами] дублировался арсайз |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
[[help:coding|Назад: Программный код]] | [[help:coding|Назад: Программный код]] | ||
- | =====Массивы===== | ||
- | * **//Массив//** - последовательный набор значений, имеющих один тип данных и обладающих одним названием. | + | ====== Массивы ====== |
- | * Элементы массива идентифицируются по индексам. | + | |
- | * Индексация ведётся с нуля. Т.е. элемент с индексом **0** - //первый// элемент массива, **1** - //второй// и т.д. | + | ===== Зачем нужны массивы ===== |
- | * Максимальный индекс массива **2147483647**. | + | |
- | * Обращение к элементу массива происходит так: сначала указывается название массива, затем в квадратных скобках - числовое выражение, равное индексу элемента, к которому производится обращение. | + | Иногда нам становится неудобно хранить множество однотипных значений в разных переменных. Например, у нас есть двадцать "одноручных мечей" и для каждого мы прописали урон в двадцати разных переменных: |
- | * На самом деле __//каждая переменная//__ в QSP __//является массивом//__.<sxh qsp> | + | |
- | яблоки = 0 | + | <sxh qsp> |
- | !эквивалентно | + | меч_одноручный_1 = 23 |
- | яблоки[0] = 0 | + | меч_одноручный_2 = 34 |
+ | меч_одноручный_3 = 27 | ||
+ | ... | ||
+ | меч_одноручный_19 = 7 | ||
+ | меч_одноручный_20 = 41 | ||
</sxh> | </sxh> | ||
- | * Соответственно для текстового массива нужно не забывать использовать символ '**$**' в имени. | + | |
- | * //**Примеры:**//<sxh qsp> | + | Даже для того, чтобы просто вывести на экран данную характеристику для каждого меча, нам придётся написать двадцать строчек кода, почти ничем не отличающихся: |
+ | |||
+ | <sxh qsp> | ||
+ | *pl "Меч одноручный №1. Урон: "+$str(меч_одноручный_1) | ||
+ | *pl "Меч одноручный №2. Урон: "+$str(меч_одноручный_2) | ||
+ | *pl "Меч одноручный №3. Урон: "+$str(меч_одноручный_3) | ||
+ | ... | ||
+ | *pl "Меч одноручный №19. Урон: "+$str(меч_одноручный_19) | ||
+ | *pl "Меч одноручный №20. Урон: "+$str(меч_одноручный_20) | ||
+ | </sxh> | ||
+ | |||
+ | Всё бы ничего, но что если нам нужно найти среди всех этих переменных ту, которая содержит максимальное число (мы ведь хотим пользоваться самым хорошим мечом)? Тут нам придётся городить огромную конструкцию условий, которая сравнивает каждую переменную со всеми остальными, и объём необходимого нам кода возрастает многократно. | ||
+ | |||
+ | Да, есть некоторые варианты решения этих двух задач без использования массивов, но они тоже весьма сложны. Куда как проще работать с однотипными данными, если они представлены в форме массива. | ||
+ | |||
+ | Если переменную мы можем вообразить в виде отдельной маленькой коробки, в которую можно положить лишь одно значение, то массив — это большой шкаф, со множеством пронумерованных ящиков (ячеек), в каждый из которых мы можем положить по одному значению. | ||
+ | |||
+ | ===== Что такое массивы ===== | ||
+ | |||
+ | **Массив** - в **QSP** это последовательный набор однотипных значений, записанных под одним общим именем. Например, вместо того, чтобы помещать урон каждого одноручного меча в отдельную переменную, мы заводим один массив, и размещаем каждое значение урона в отдельных ячейках этого самого одного единственного массива: | ||
+ | |||
+ | <sxh qsp> | ||
+ | меч_одноручный[0] = 23 & ! нумерация ячеек массива начинается с нуля | ||
+ | меч_одноручный[1] = 34 | ||
+ | меч_одноручный[2] = 27 | ||
+ | ... | ||
+ | меч_одноручный[18] = 7 | ||
+ | меч_одноручный[19] = 41 & ! значение для двадцатого меча лежит в ячейке под номером 19 | ||
+ | </sxh> | ||
+ | |||
+ | Как видно из примера, чтобы записать значение в отдельную ячейку массива, мы должны: | ||
+ | |||
+ | * написать имя массива | ||
+ | * затем без пробелов, не отступая от имени массива, в квадратных скобках написать номер ячейки, в которую хотим поместить значение | ||
+ | * затем поставить знак ''**=**'' (операция присваивания) | ||
+ | * и уже после знака равно написать нужное значение. | ||
+ | |||
+ | В нашем примере массив называется "меч_одноручный", а в квадратных скобках мы указываем номера ячеек этого массива. | ||
+ | |||
+ | ==== Создание массива ==== | ||
+ | |||
+ | Записывая значения хотя бы в одну ячейку массива, мы тем самым **создаём** (инициализируем) весь массив. | ||
+ | |||
+ | * Ячейки массива так же называются **элементами**. | ||
+ | * Каждый массив состоит из множества элементов, и у каждого элемента есть собственный номер. | ||
+ | * Номера элементов начинаются с нуля и не повторяются. | ||
+ | * Нумерация элементов массива не прерывается. То есть, например, не может в массиве существовать четвёртый элемент, но отсутствовать второй и третий элемент. Если мы создадим только нулевой и первый, а так же четвёртый, элементы массива, второй и третий элементы будут созданы автоматически: <sxh qsp> | ||
+ | mass[0]=13 | ||
+ | mass[1]=19 | ||
+ | mass[4]=23 | ||
+ | ! элементы mass[2] и mass[3] созданы автоматически и хранят значения по умолчанию | ||
+ | </sxh> | ||
+ | * Максимальный возможный номер ячейки массива ''**2147483647**''. | ||
+ | * Минимально возможный номер ячейки массива ''**0**''. То есть QSP не допускает создания ячеек с отрицательным индексом и не работает с такими ячейками, игнорируя команды присвоения, и возвращая значение по умолчанию при попытке извлечь из такой ячейки значение. | ||
+ | |||
+ | ==== Типы данных в массивах ==== | ||
+ | |||
+ | Массив можно представлять себе как список значений. Если вам нужно хранить только одно значение, достаточно обычной переменной, но если вам нужно сохранить множество однотипных значений, как некий список, то обязательно используйте массив. Например, вы можете вести список имён всех встреченных персонажей: | ||
+ | |||
+ | <sxh qsp> | ||
+ | $встреченные_неписи[0] = "Домовёнок Нафаня" | ||
+ | $встреченные_неписи[1] = "Девочка Оля" | ||
+ | $встреченные_неписи[2] = "Лариса Петровна" | ||
+ | $встреченные_неписи[3] = "Баба Яга" | ||
+ | </sxh> | ||
+ | |||
+ | В данном примере мы помещали в массив строковые значения. Чтобы поместить в ячейку массива строковое значение, нужно поставить перед именем массива символ ''%%$%%'' (префикс типа). | ||
+ | |||
+ | То же самое и в случае, когда мы хотим получить значение из ячейки массива: если мы хотим получить строковое значение, нужно поставить символ ''%%$%%'' перед именем массива. | ||
+ | |||
+ | И точно так же это работает для числовых значений и кортежей: - Если нам нужно присвоить ячейке массива, или получить из неё, числовое значение, никаких символов мы перед именем массива не ставим (без префикса типа). - Если нам нужно присвоить ячейке массива, или получить из неё, кортеж, ставим символ ''%'' перед именем массива (указываем префикс типа). | ||
+ | |||
+ | Примеры: | ||
+ | |||
+ | <sxh qsp> | ||
$яблоки[0]='антоновка' | $яблоки[0]='антоновка' | ||
$яблоки[1]='белый налив' | $яблоки[1]='белый налив' | ||
Строка 23: | Строка 100: | ||
сорт_яблока[1] = 2 | сорт_яблока[1] = 2 | ||
сорт_яблока[2] = 4 | сорт_яблока[2] = 4 | ||
+ | |||
+ | %сорта_в_корзине[0] = [1, 4] | ||
+ | %сорта_в_корзине[1] = [2, 4] | ||
+ | %сорта_в_корзине[2] = [1, 2] | ||
*pl $яблоки[сорт_яблока[номер_яблока]] | *pl $яблоки[сорт_яблока[номер_яблока]] | ||
</sxh> | </sxh> | ||
- | * Массивы могут индексироваться через строки. Регистр символов данной строки не имеет значения. Примеры:<sxh qsp> | ||
- | $любимый_сорт['иван'] = $яблоки[2] | ||
- | любимое_число['Алексей'] = 5 | ||
- | $item_loc['палка'] = 'лес' | ||
- | </sxh> | ||
- | * Существует упрощённый синтаксис чтения последнего и добавления нового элемента в массив. Если индекс элемента не указан: | ||
- | * при записи будет выбран элемент, следующий за последним. Например: <sxh qsp> | ||
- | $objs[] = 'Напильник' &! Если массив был пустой, то | ||
- | $objs[] = 'Топор' &! [0] = 'Напильник', | ||
- | $objs[] = 'Доска' &! [1] = 'Топор', [2] = 'Доска'</sxh> | ||
- | * при чтении будет выбран последний элемент. Например: <sxh qsp> | ||
- | $a = $objs[] &! 'Доска' из примера выше | ||
- | a = сорт_яблока[] &! 4 из примера выше</sxh> | ||
- | **Примечание:** При добавлении в массив элемента со строковым индексом((массив['строка'] = значение)) элемент добавляется в конец массива. //Настоятельно __не__ рекомендуется сочетать числовые и строковые индексы в пределах одного массива.// | + | **В одном массиве** допускается хранить значения любых типов, однако строго рекомендуется хранить в одном массиве только значения одного типа: либо строковые, либо числовые, либо кортежи, — во избежание возможных [[glossary:bag|багов]]. |
- | **Примечание:** В силу особенностей платформы числовые и текстовые массивы связаны между собой: добавление элемента в //'массив'// добавляет пустой элемент в //'$массив'// и наоборот со всеми вытекающими последствиями. | + | **В одной ячейке массива** можно хранить значение только одного типа! Если вы запишете в ячейку, которая хранит строку, числовое значение — это числовое значение "затрёт" строковое. И точно так же со значением любого другого типа. |
- | **Примечание:** Настоятельно __не__ рекомендуется использовать большие числовые индексы без необходимости. | + | ==== Обработка массивов ==== |
- | ====Функции и операторы==== | + | Преимущество работы с массивами по сравнению с обычными переменными раскрывается тогда, когда нам приходится много раз повторять одну и ту же операцию над однотипными значениями. |
- | * **KILLVAR** //[$название массива]//,//[#индекс элемента]// - удаление элемента массива. | + | В примере из начала статьи мы помещали наносимый одноручным мечом урон для двадцати разных мечей в двадцать отдельных переменных и видели, что даже такая простая операция, как вывод значений всех этих переменных на экран требует огромного количества кода. Совсем другое дело, когда мы поместили наши данные в массив, ведь мы можем перебрать весь массив с помощью простого цикла: |
- | * Если индекс элемента не указан, то удаляется весь массив. | + | |
- | * Если оператор вызван без аргументов, то удаляются все переменные | + | |
- | * **KILLALL** - оператор эквивалентен конструкции "KILLVAR & KILLOBJ"((обычно применяется в начале игры, чтобы при возврате в начальную локацию после неудачного прохождения какого-то этапа игры обнулить все переменные (в противном случае, может оказаться, что запертые двери уже открыты, жена похищена до свадьбы, а Баба-Яга уже отдала кому-то нужный клубочек) )) | + | |
- | * При удалении элемента все следующие за ним элементы сдвигаются на позицию вверх.<sxh qsp> | + | |
- | a[0]=4 | + | |
- | a[1]=3 | + | |
- | a[2]=23 | + | |
- | a[3]=15 | + | |
- | KILLVAR 'a',1 | + | |
- | !теперь массив выглядит так: | + | |
- | a[0]=4 | + | |
- | a[1]=23 | + | |
- | a[2]=15 | + | |
- | </sxh> | + | |
- | * //Примеры://<sxh qsp> | + | |
- | KILLVAR &! удаляет все переменные, массивы | + | |
- | KILLVAR 'a' &! удаляет массив 'a' | + | |
- | KILLVAR 'a',3 &! удалит из массива 'a' элемент с индексом 3. | + | |
- | </sxh> | + | |
- | * **COPYARR** //[$приёмник]//**,**//[$источник]//**,**//[#начало]//**,**//[#количество]// - копирование в массив-приёмник //[#количество]// элементов из массива-источника начиная с элемента под номером //[#начало]//. Размер массива-приёмника при копировании не имеет значения. | + | |
- | * Параметр //[#количество]// является необязательным. По умолчанию - до конца массива-источника. | + | |
- | * Параметр //[#начало]// является необязательным. По умолчанию - 0 | + | |
- | * В силу особенностей движка при копировании массива //'массив1'// в //'массив2'// копируется также //'$массив1'// в //'$массив2'//. | + | |
- | * //Примеры://<sxh qsp> | + | |
- | COPYARR '$a','$b' | + | |
- | COPYARR 'a','b' | + | |
- | COPYARR $arrname1,$arrname2,10,5 | + | |
- | COPYARR 'a<<$arrname1>>','a<<$arrname2>>' | + | |
- | </sxh> | + | |
- | * **ARRSIZE(**//[$имя]//**)** - функция возвращает число элементов в массиве с названием //[$имя]//. | + | |
- | * В силу особенностей движка возвращается наибольшее из числа элементов '//массива//' и '//$массива//'. | + | |
- | * //Примеры://<sxh qsp> | + | |
- | n = ARRSIZE('a') | + | |
- | n = ARRSIZE('$a') | + | |
- | !Результат будет одинаковый | + | |
- | </sxh> | + | |
- | * **ARRPOS(**//[#начало]//,//[$имя_массива]//,//[значение]//**)** - возвращает индекс элемента массива, равного значению. Поиск начинается с элемента с заданным номером; индексация элементов массива ведётся с нуля. Если указанное значение не найдено, функция возвращает **-1**. | + | |
- | * Параметр //[#начало]// может отсутствовать, при этом он принимается равным **0**. | + | |
- | * **Важно:** в более новых версиях (//Quest Navigator//) необязательный параметр //[#начало]// переставлен последним((**ARRPOS(**//[$имя_массива]//**,**//[значение]//**,**//[#начало]//**)**)). | + | |
- | * //Примеры://<sxh qsp> | + | |
- | !Поиск строки 'This' в текстовом массиве "$A" | + | |
- | ARRPOS(0,'$A','This') | + | |
- | !Поиск числа 65 в массиве "A" (два элемента массива игнорируются) | + | |
- | ARRPOS(2,'A',65) | + | |
- | !Поиск строки 'test' среди значений массива "$B" | + | |
- | ARRPOS('$B','test') | + | |
- | </sxh> | + | |
- | * См. также функции "**MAX**, **MIN**" ([[help:coding?&#bazovye_funkcii|Программный код]]) | + | |
- | * **ARRCOMP(**//[#начало]//,//[$имя_массива]//,//[$шаблон]//**)** - возвращает индекс элемента массива, соответствующего //__регулярному выражению__//. Поиск начинается с элемента с заданным номером; индексация элементов массива ведётся с нуля. Если указанное значение не найдено, функция возвращает **-1**. | + | |
- | * Поиск работает только по текстовым массивам (символ '$' в названии можно опустить). | + | |
- | * Параметр //[#начало]// может отсутствовать, при этом он принимается равным **0**. | + | |
- | * **Важно:** в более новых версиях (//Quest Navigator//) необязательный параметр //[#начало]// переставлен последним((**ARRCOMP(**//[$имя_массива]//**,**//[$шаблон]//**,**//[#начало]//**)**)). | + | |
- | * //Примеры://<sxh qsp> | + | |
- | !Поиск строки 'This' среди элементов массива "$A" | + | |
- | ARRCOMP(0,'A','This') | + | |
- | !'Поиск строки, соответствующей регулярному выражению "abc\d+" | + | |
- | (первые два элемента массива игнорируются)' | + | |
- | ARRCOMP(2,'A','abc\d+') | + | |
- | !'аналогично предыдущему примеру, но поиск осуществляется | + | |
- | по всем элементам массива' | + | |
- | ARRCOMP(0,'A','.*string.*') | + | |
- | ARRCOMP('A','This') &! эквивалентно 1му варианту | + | <sxh qsp> |
+ | меч_одноручный[0] = 23 & ! нумерация ячеек массива начинается с нуля | ||
+ | меч_одноручный[1] = 34 | ||
+ | меч_одноручный[2] = 27 | ||
+ | ... | ||
+ | меч_одноручный[18] = 7 | ||
+ | меч_одноручный[19] = 41 & ! значение для двадцатого меча лежит в ячейке под номером 19 | ||
+ | |||
+ | ! выводим на экран список с помощью цикла | ||
+ | loop i=0 while i<20 step i+=1: | ||
+ | *pl "Меч одноручный №<<i+1>>. Урон: "+$str(меч_одноручный[i]) | ||
+ | end | ||
</sxh> | </sxh> | ||
- | ====Двумерные массивы с числовыми индексами==== | + | В этом примере для вывода на экран всех значений из всех двадцати ячеек массива нам потребовалось написать всего три строчки кода. |
- | Пример симуляции двумерного массива | + | А вот как выглядит поиск одноручного меча с наибольшим значением урона: |
<sxh qsp> | <sxh qsp> | ||
- | ! Индексы i1 0..8 | + | pos = arrpos('меч_одноручный',max('меч_одноручный')) |
- | i1_max=9 | + | *pl "Наибольший урон имеет Меч одноручный №<<pos+1>>: "+$str(меч_одноручный[pos]) |
+ | </sxh> | ||
- | ! Индексы i2 0..5 | + | В обоих этих примерах вместо указания конкретного номера ячейки массива, при получении данных из массива, мы подставляли значение переменной. Именно эта возможность позволяет так легко и быстро обрабатывать множество данных в массивах, и делает работу с ними более удобной, чем с обычными переменными. |
- | i2_max=6 | + | |
- | ! Заполнение данных массива | + | ==== Индексирование элементов массива ==== |
- | i1=0 | + | |
- | :ПрыгЗадатьМассив1 | + | |
- | i2=0 | + | |
- | :ПрыгЗадатьМассив2 | + | |
- | $ДвумерныйМассив[i1*i2_max+i2]='[<<i1>>,<<i2>>]' | + | |
- | i2+=1 | + | |
- | if i2<i2_max : Jump 'ПрыгЗадатьМассив2' | + | |
- | i1+=1 | + | |
- | if i1<i1_max : Jump 'ПрыгЗадатьМассив1' | + | |
+ | Выше мы писали, что ячейки массивов нумеруются подряд, начиная с нуля, и нумерация эта не прерывается. Номер ячейки массива называется **числовым индексом ячейки массива**. | ||
- | ! Вывод данных массива | + | <sxh qsp> |
- | i1=0 | + | ! ячейки массивов индексируются через числа |
- | :ПрыгВыводМассива1 | + | $любимый_сорт[3] = $яблоки[2] |
- | *Nl | + | любимое_число[19] = 5 |
- | i2=0 | + | $item_loc[0] = 'лес' |
- | :ПрыгВыводМассива2 | + | </sxh> |
- | *P $ДвумерныйМассив[i1*i2_max+i2]+' ' | + | |
- | i2+=1 | + | |
- | if i2<i2_max : Jump 'ПрыгВыводМассива2' | + | |
- | i1+=1 | + | |
- | if i1<i1_max : Jump 'ПрыгВыводМассива1' | + | |
- | *Nl | + | |
- | !{Результат | + | **Важно!** Настоятельно не рекомендуется использовать большие числовые индексы без необходимости. |
- | [0,0] [0,1] [0,2] [0,3] [0,4] [0,5] | + | |
- | [1,0] [1,1] [1,2] [1,3] [1,4] [1,5] | + | |
- | [2,0] [2,1] [2,2] [2,3] [2,4] [2,5] | + | |
- | [3,0] [3,1] [3,2] [3,3] [3,4] [3,5] | + | |
- | [4,0] [4,1] [4,2] [4,3] [4,4] [4,5] | + | |
- | [5,0] [5,1] [5,2] [5,3] [5,4] [5,5] | + | |
- | [6,0] [6,1] [6,2] [6,3] [6,4] [6,5] | + | |
- | [7,0] [7,1] [7,2] [7,3] [7,4] [7,5] | + | |
- | [8,0] [8,1] [8,2] [8,3] [8,4] [8,5] | + | |
- | } | + | |
- | !Получение индексов массива через функцию ARRPOS | + | **QSP** позволяет создавать для элементов массивов не только числовые, но и строковые индексы. Иными словами массивы могут //индексироваться через строки//. Примеры: |
- | $Поиск='[2,5]' | + | <sxh qsp> |
+ | ! ячейки массивов индексируются через строки | ||
+ | $любимый_сорт['Иван'] = $яблоки[2] | ||
+ | любимое_число['Алексей'] = 5 | ||
+ | $item_loc['палка'] = 'лес' | ||
+ | </sxh> | ||
- | i1=ARRPOS('$ДвумерныйМассив',$Поиск)/i2_max | + | Регистр символов в строковом индексе массива значения не имеет: |
- | i2=ARRPOS('$ДвумерныйМассив',$Поиск) mod i2_max | + | |
- | + | ||
- | if ARRPOS('$ДвумерныйМассив',$Поиск)<>-1 : | + | |
- | *Nl $Поиск+'=[<<i1>>,<<i2>>]' | + | |
- | else | + | |
- | *Nl 'Элемент не найден' | + | |
- | end | + | |
- | !{Результат | + | |
- | [2,5]=[2,5] | + | |
- | } | + | |
+ | <sxh qsp> | ||
+ | $любимый_сорт['иван'] = 'Антоновка' | ||
+ | *pl $любимый_сорт['ИВАН'] & ! выведет строку Антоновка | ||
</sxh> | </sxh> | ||
+ | Есть небольшая хитрость в том, как назначаются строковые индексы ячейкам массивов. Когда вы инициализируете (создаёте, объявляете) новую ячейку массива со строковым индексом, происходит следующее: | ||
+ | * Плеер создаёт новую ячейку с новым числовым индексом, следующим по порядку. Например, если в массиве уже были созданы три ячейки, создаётся ячейка с числовым индексом ''%%3%%''. | ||
+ | * Затем плеер "прикрепляет" указанный строковый индекс к числовому. | ||
+ | Поэтому, если вы создаёте ячейку со строковым индексом, вы можете получать из неё значения в том числе и по числовому индексу: | ||
+ | <sxh qsp> | ||
+ | яблоки['у Паши']=37 | ||
+ | яблоки['у Даши']=19 | ||
+ | яблоки['у Лёши']=11 | ||
+ | *pl яблоки[0] & ! выведет на экран число 37 | ||
+ | *pl яблоки[1] & ! выведет на экран число 19 | ||
+ | *pl яблоки[2] & ! выведет на экран число 11 | ||
+ | </sxh> | ||
- | ====Двумерные массивы с текстовыми индексами==== | + | **Настоятельно рекомендуется** использовать для индексирования или только числовые индексы, или только строковые индексы. |
+ | |||
+ | Текстовые индексы позволяют обойти ограничение массивов на начало нумерации только с нуля: | ||
- | Пример работы с массивом имеющим текстовые индексы | ||
<sxh qsp> | <sxh qsp> | ||
- | ! Индексы i1 0..3 | + | $item['-2']='Палка' |
- | i1_max=4 | + | $item['-1']='Дрель' |
+ | $item['0']='Радиоактивный пепел' | ||
+ | </sxh> | ||
- | ! Индексы i2 0..5 | + | ==== Многомерные массивы ==== |
- | i2_max=6 | + | |
- | ! Заполнение данных массива | + | В **QSP** есть возможность создавать многомерные массивы, используя для этого специальные индексы: |
- | i1=0 | + | |
- | :ПрыгЗадатьМассив1 | + | |
- | i2=0 | + | |
- | :ПрыгЗадатьМассив2 | + | |
- | ! Знак двоеточие используется как разделитель | + | |
- | ! между двумя численными индексами переведенными в текст | + | |
- | $ДвумерныйМассивТекстовыйИндекс['<<i1>>:<<i2>>']='[<<i1>>,<<i2>>]' | + | |
- | ! $МассивИндекс нужен для дальнейшего поиска через ARRPOS/ARRCOMP | + | |
- | $МассивИндекс['<<i1>>:<<i2>>']='<<i1>>:<<i2>>' | + | |
- | ! МассивПорядок нужен для использования KILLVAR | + | |
- | МассивПорядок['<<i1>>:<<i2>>']=ARRSIZE('МассивПорядок') | + | |
- | ! Добавлять новый элемент и удалять нужно | + | |
- | !только одновременно в 3х массивах | + | |
- | + | ||
- | i2+=1 | + | |
- | if i2<i2_max : Jump 'ПрыгЗадатьМассив2' | + | |
- | i1+=1 | + | |
- | if i1<i1_max : Jump 'ПрыгЗадатьМассив1' | + | |
+ | <sxh qsp> | ||
+ | $map[1,2]='лес' | ||
+ | $map[1,3]='лес' | ||
+ | $map[2,2]='лес' | ||
+ | $map[4,0]='река' | ||
+ | </sxh> | ||
- | ! Вывод данных массива | + | В данном примере в квадратных скобках вместо номера ячейки мы указываем числа, перечисляемые через запятую. Таким образом мы создаём ячейки **двумерного** массива. |
- | i1=0 | + | |
- | :ПрыгВыводМассива1 | + | |
- | *Nl | + | |
- | i2=0 | + | |
- | :ПрыгВыводМассива2 | + | |
- | *P $ДвумерныйМассивТекстовыйИндекс['<<i1>>:<<i2>>']+' ' | + | |
- | i2+=1 | + | |
- | if i2<i2_max : Jump 'ПрыгВыводМассива2' | + | |
- | i1+=1 | + | |
- | if i1<i1_max : Jump 'ПрыгВыводМассива1' | + | |
- | *Nl | + | Числа в квадратных скобках — это строка значений, или **[[help:tuples|кортеж]]**. |
- | !{ Результат | + | Используя для индексации элементов массивов кортежи, мы можем создавать трёхмерные, четырёхмерные, и вообще сколькиугодно-мерные массивы: |
- | [0,0] [0,1] [0,2] [0,3] [0,4] [0,5] | + | |
- | [1,0] [1,1] [1,2] [1,3] [1,4] [1,5] | + | |
- | [2,0] [2,1] [2,2] [2,3] [2,4] [2,5] | + | |
- | [3,0] [3,1] [3,2] [3,3] [3,4] [3,5] | + | |
- | } | + | |
+ | <sxh qsp> | ||
+ | $space[0,-2,9] = 'космический корабль' | ||
+ | value_time[12,33,1,366] = 137 | ||
+ | макрокосмос_миллиардов_микрокосм[12,34,12,98,76,30,11,19,137,90] = 991112 | ||
+ | </sxh> | ||
- | !Получение индексов массива через функцию ARRPOS | + | Для многомерных индексов можно использовать не только числовые значения, но и строковые: |
- | $Поиск='[3,0]' | + | |
- | N=ARRPOS('$ДвумерныйМассивТекстовыйИндекс',$Поиск) | + | <sxh qsp> |
- | if N<>-1: | + | данные['таблица_данных',0,1]=73 |
- | !Ищем разделитель ':' в индексе | + | яблоки['Паша','левый карман']=91 |
- | K=STRPOS($МассивИндекс[N],':') | + | яблоки['Миша','правый карман']=10 |
+ | $map[12,14,'слой_подземелья']="стена" | ||
+ | </sxh> | ||
- | i1=VAL(MID($МассивИндекс[N],0,K-1)) | + | Есть небольшая хитрость в том, как назначаются многомерные индексы ячейкам массивов. Когда вы инициализируете (создаёте; объявляете) новую ячейку массива с многомерным индексом, происходит следующее: |
- | i2=VAL(MID($МассивИндекс[N],K+1,LEN($МассивИндекс[N])-K)) | + | |
- | *NL $Поиск+'=[<<i1>>,<<i2>>]' | + | * Плеер создаёт новую ячейку с новым **числовым** индексом, следующим по порядку. Например, если в массиве уже были созданы семь ячеек, создаётся ячейка с числовым индексом ''%%7%%''. |
- | else | + | * Затем плеер "прикрепляет" указанный многомерный индекс к числовому. |
- | *Nl 'Элемент не найден' | + | |
- | end | + | |
+ | Поэтому, если вы создаёте ячейку с многомерным индексом, вы можете получать из неё значения в том числе и по числовому индексу: | ||
- | !{ Результат | + | <sxh qsp> |
- | [3,0]=[3,0] | + | яблоки['у Паши','левый карман']=37 |
- | } | + | яблоки['у Паши','правый карман']=5 |
+ | яблоки['у Лёши','левый карман']=11 | ||
+ | яблоки['у Лёши','правый карман']=19 | ||
+ | *pl яблоки[0] & ! выведет на экран число 37 | ||
+ | *pl яблоки[1] & ! выведет на экран число 5 | ||
+ | *pl яблоки[2] & ! выведет на экран число 11 | ||
+ | *pl яблоки[3] & ! выведет на экран число 19 | ||
+ | </sxh> | ||
- | *NL | + | **Настоятельно рекомендуется** использовать для индексирования или только числовые индексы, или только многомерные индексы. |
- | !Удаление элемента массива через текстовый индекс | + | |
- | $Удалить='<<i1>>:<<i2>>' | + | |
- | *NL 'Удаляем элемент с индексом <<i1>>:<<i2>>' | + | |
- | !Получаем номер элемента | + | Поскольку многомерные индексы - это кортежи: - можно использовать переменные типа **кортеж** для подстановок в индексах таких массивов: <sxh qsp> |
+ | %coords = [120, 450, -37] | ||
+ | $map[%coords] = 'Alien' | ||
+ | </sxh> - Запись с дополнительным набором скобок эквивалентна записи с одним набором скобок при указании индекса ячейки массива: <sxh qsp> | ||
+ | $array[1, 2, 137] | ||
+ | ! эквивалентно | ||
+ | $array[[1, 2, 137]] | ||
+ | </sxh> | ||
- | N=МассивПорядок[$Удалить] | + | ==== Упрощённый доступ к ячейкам массивов ==== |
+ | На самом деле каждая переменная в QSP является массивом, состоящим из одной единственной ячейки: | ||
- | !Удаляем элемент | + | <sxh qsp> |
- | KILLVAR '$ДвумерныйМассивТекстовыйИндекс', N | + | яблоки = 0 |
- | KILLVAR '$МассивИндекс', N | + | !эквивалентно |
- | KILLVAR 'МассивПорядок', N | + | яблоки[0] = 0 |
+ | </sxh> | ||
- | !Еще раз выводим данные массива | + | то есть, если мы создаём переменную с именем "яблоко", мы тем самым создаём массив с именем "яблоко", состоящий из одной ячейки. |
- | i1=0 | + | Таким образом вы всегда можете получить или присвоить данные нулевой ячейке массива, просто указав его имя: |
- | :ПрыгВыводМассива3 | + | |
- | *Nl | + | |
- | i2=0 | + | |
- | :ПрыгВыводМассива4 | + | |
- | if $ДвумерныйМассивТекстовыйИндекс['<<i1>>:<<i2>>']<>'': | + | |
- | *P $ДвумерныйМассивТекстовыйИндекс['<<i1>>:<<i2>>']+' ' | + | |
- | else | + | |
- | *P '[DEL] ' | + | |
- | end | + | |
- | i2+=1 | + | |
- | if i2<i2_max : Jump 'ПрыгВыводМассива4' | + | |
- | i1+=1 | + | |
- | if i1<i1_max : Jump 'ПрыгВыводМассива3' | + | |
+ | <sxh qsp> | ||
+ | ! присваиваем нулевой ячейке массива '$COUNTER' строковое значение | ||
+ | $counter='счётчик' | ||
+ | *pl $counter[0] & ! проверяем | ||
+ | ! присваиваем нулевым ячейкам массивов red, green, blue значения | ||
+ | set red[0],green[0],blue[0]=234,198,77 | ||
+ | *pl "red: <<red>>, green: <<green>>, blue: <<blue>>" & ! проверяем | ||
+ | </sxh> | ||
+ | Существует упрощённый синтаксис чтения последнего и добавления нового элемента в массив. Для этого квадратные скобки пишутся без указания индекса: | ||
- | !{ Результат | + | * при записи значения в массив будет создан новый элемент сразу за последним. Например: <sxh qsp> |
- | Удаляем элемент с индексом 3:0 | + | |
- | [0,0] [0,1] [0,2] [0,3] [0,4] [0,5] | + | |
- | [1,0] [1,1] [1,2] [1,3] [1,4] [1,5] | + | |
- | [2,0] [2,1] [2,2] [2,3] [2,4] [2,5] | + | |
- | [DEL] [3,1] [3,2] [3,3] [3,4] [3,5] | + | |
- | } | + | |
+ | ! Если массив был пустой, то | ||
+ | $objs[] = 'Напильник' &! $objs[0] = 'Напильник' | ||
+ | $objs[] = 'Топор' | ||
+ | &! $objs[1] = 'Топор' | ||
+ | $objs[] = 'Доска' | ||
+ | &! $objs[2] = 'Доска' | ||
</sxh> | </sxh> | ||
+ | * при получении значения из массива будет выбран последний элемент. Например: <sxh qsp> | ||
+ | *pl $objs[] &! 'Доска' из примера выше | ||
+ | </sxh> | ||
- | ====Массив переменных==== | + | ===== Функции и операторы для работы с массивами ===== |
- | Пример использования индекса в названии массива | + | * ''%%KILLVAR [$имя_массива], [индекс_элемента]%%'' - удаление элемента с индексом ''%%[индекс_элемента]%%'' из массива с названием ''%%[$имя_массива]%%''. Название массива всегда нужно писать в кавычках. Пример: <sxh qsp> |
+ | ! удаление по числовому индексу | ||
+ | killvar 'яблоко',3 | ||
+ | ! удаление элемента по строковому индексу | ||
+ | killvar '$item_loc','палка' | ||
+ | ! удаление элемента по многомерному индексу | ||
+ | killvar '$space',[0,-2,9] | ||
+ | </sxh> | ||
+ | * Если индекс элемента не указан, то удаляется весь массив. <sxh qsp> | ||
+ | ! удаляем массив $map целиком | ||
+ | killvar '$map' | ||
+ | </sxh> | ||
+ | * Если оператор вызван без аргументов, то удаляются все массивы и переменные в игре! <sxh qsp> | ||
+ | ! удаляем все массивы и переменные | ||
+ | KILLVAR | ||
+ | </sxh> | ||
+ | * При удалении элемента все следующие за ним элементы сдвигаются на позицию вверх. <sxh qsp> | ||
+ | a[0]=4 | ||
+ | a[1]=3 | ||
+ | a[2]=23 | ||
+ | a[3]=15 | ||
+ | KILLVAR 'a',1 | ||
+ | !теперь массив выглядит так: | ||
+ | a[0]=4 | ||
+ | a[1]=23 | ||
+ | a[2]=15 | ||
+ | </sxh> | ||
+ | * ''%%KILLALL%%'' - оператор эквивалентен конструкции "''%%KILLVAR & KILLOBJ%%''", то есть удаляет все переменные/массивы в игре, а так же очищает Окно предметов. Обычно применяется в начале игры, чтобы при возврате в начальную локацию после неудачного прохождения какого-то этапа игры обнулить все переменные (в противном случае, может оказаться, что запертые двери уже открыты, жена похищена до свадьбы, а Баба-Яга уже отдала кому-то нужный клубочек). | ||
+ | * ''%%COPYARR [$приёмник],[$источник],[#начало],[#количество]%%'' - копирование в массив-приёмник ''%%[#количество]%%'' элементов из массива-источника начиная с элемента под номером ''%%[#начало]%%''. Размер массива-приёмника при копировании не имеет значения. | ||
+ | * Параметр ''%%[#количество]%%'' является необязательным. По умолчанию - до конца массива-источника. | ||
+ | * Параметр ''%%[#начало]%%'' является необязательным. По умолчанию - ''%%0%%''. | ||
+ | * Не имеет значения, указываете ли вы ''%%$%%'' или ''%'' перед названием массива, или нет. Копируются элементы с любыми типами значений. | ||
+ | * Примеры: <sxh qsp> | ||
+ | COPYARR '$a','$b' | ||
+ | COPYARR 'a','b' | ||
+ | ! $arrname1, $arrname2 = 'arr', 'bar' | ||
+ | COPYARR $arrname1,$arrname2,10,5 | ||
+ | COPYARR 'a<<$arrname1>>','a<<$arrname2>>' | ||
+ | </sxh> | ||
+ | * ''%%SORTARR [$имя_массива], [#порядок]%%'' — Данный оператор сортирует указанный массив. Параметр ''%%[#порядок]%%'' опционален. Если не указан или равен 0, то сортирует массив по возрастанию (от меньшего к большему). Если равен 1, то сортирует массив по убыванию (от большего к меньшему). | ||
+ | * Может сортировать массивы любых типов (числа, строки, кортежи), но не допускается смешивать значения разных типов в одном массиве. | ||
+ | * Для указания типа сортируемых значений нужно указать префикс типа как часть имени массива (''%%$%%'', ''%''). | ||
+ | * Пример сортировки текстового массива: <sxh qsp> | ||
+ | $a[] = 'nn' | ||
+ | $a[] = 'zz' | ||
+ | $a[] = 'aa' | ||
+ | sortarr '$a' | ||
+ | !проверяем результат сортировки: | ||
+ | loop local i=0 while i<arrsize('$a') step i+=1: | ||
+ | *pl $a[i] | ||
+ | end | ||
+ | </sxh> | ||
+ | * ''%%SCANSTR [$имя_массива], [$текст_для_разбора], [$регэксп], [#номер_группы]%%'' — в массив ''%%[$имя_массива]%%'' помещаются строки, соответствующие [[help:regexp|регулярному выражению]] ''%%[$регэксп]%%'', которые будут найдены в строке ''%%[$текст_для_разбора]%%''. Если указан параметр ''%%[#номер_группы]%%'', в массив будет помещаться не вся строка, соответствующая регулярному выражению, а лишь часть, соответствующая указанной группе в этом регулярном выражении. Примеры: <sxh qsp> | ||
+ | ! вытаскиваем из строки все слова: | ||
+ | $text = 'Шла Саша по шоссе, а Грека через реку.' | ||
+ | scanstr '$words', $text, '\b\w+\b' | ||
+ | !В массиве $words окажутся значения: 'Шла', 'Саша', 'по', 'шоссе', 'а', 'Грека', 'через', 'реку' | ||
- | <sxh qsp> | + | ! разбиваем строку по разделителю: |
- | ! Индексы i1 0..5 | + | $text = 'утро|день|вечер|ночь' |
- | i1_max=6 | + | scanstr '$words', $text, '[^|]+' |
+ | !В массиве $words окажутся значения: 'утро', 'день', 'вечер', 'ночь' | ||
- | ! Индексы i2 0..2 | + | ! вытаскиваем из строки все слова, помещённые в квадратные скобки, но без квадратных скобок: |
- | i2_max=3 | + | $text = '[first] ignoredtext [second][third] also ignored' |
+ | scanstr '$words', $text, '\[(.*?)\]', 1 | ||
+ | !В массиве $words окажутся значения: 'first', 'second', 'third' | ||
+ | </sxh> | ||
+ | * ''%%ARRITEM([$имя_массива],[индекс_элемента])%%'' — возвращает значение элемента массива с названием ''%%[$имя_массива]%%'' по указанному индексу. То есть функция извлекает значение из указанной ячейки массива. Примеры: <sxh qsp> | ||
+ | ! выводим значение элемента с индексом 3 | ||
+ | *pl $arritem('$mass', 3) | ||
+ | ! выводим значение элемента с текстовым индексом | ||
+ | *pl $arritem('$mass', 'Петя') | ||
+ | ! выводим значение элемента с многомерным индексом | ||
+ | *pl $arritem('$mass', [-2, 9, 0]) | ||
+ | </sxh> Эта функция может быть полезна для извлечения значений, если имя массива заранее не известно. Пример: <sxh qsp> | ||
+ | ! выводим содержимое нескольких массивов без использования ''**DYNAMIC**'': | ||
+ | $array_name[]='mass_1' | ||
+ | $array_name[]='mass_2' | ||
+ | $array_name[]='mass_3' | ||
+ | $array_name[]='mass_4' | ||
+ | $array_name[]='mass_5' | ||
+ | ! внешний цикл перебирает имена массивов | ||
+ | loop local j=0 while j<arrsize('$array_name') step j+=1: | ||
+ | ! внутренний цикл выводит содержимое массивов | ||
+ | loop local i=0 while i<arrsize($array_name[j]) step i+=1: | ||
- | ! Заполнение данных массива | + | *pl arritem($array_name[j], i) |
- | i1=0 | + | end |
- | :ПрыгЗадатьМассив1 | + | end |
- | i2=0 | + | </sxh> |
- | :ПрыгЗадатьМассив2 | + | * ''%%SETVAR [$имя_массива], [значение], [индекс]%%'' — устанавливает значение элемента массива с названием ''%%[$имя_массива]%%'' по указанному индексу. То есть оператор присваивает значение указанной ячейке массива. Префикс имени переменной указывает тип значения, которое нужно записать в элемент массива (как с обычными присваиваниями). Параметр ''[индекс]'' опционален. Если этот параметр не указан, то значение присваивается 0-му элементу. Значение и индекс могут быть любых типов. Примеры: <sxh qsp> |
- | !названия заполняемых массивов | + | SETVAR 'A', 65 |
- | !$МассивПеременных0 , $МассивПеременных1 , $МассивПеременных2 | + | SETVAR '$X', 'name', 4 |
- | DYNAMIC {$МассивПеременных}+i1+{['<<i2>>']='[<<i1>>,<<i2>>]' } | + | SETVAR '$X', 'name', 'string index' |
- | i2+=1 | + | SETVAR '%Q', ['пример', 'кортежа'], 3 |
- | if i2<i2_max : Jump 'ПрыгЗадатьМассив2' | + | SETVAR '%Q', ['пример', 'кортежа'], [x, y] |
- | i1+=1 | + | </sxh> Данный оператор дополняет функцию ''**ARRITEM**'' и позволяет избегать использования ''DYNAMIC'' в некоторых случаях. |
- | if i1<i1_max : Jump 'ПрыгЗадатьМассив1' | + | * ''%%ARRSIZE([$имя_массива])%%'' - функция возвращает число элементов массива с названием ''%%[$имя_массива]%%''. |
+ | * Не имеет значения, указываете ли вы ''%%$%%'' или ''%%%%%'' перед названием массива или нет. Подсчитывается общее число ячеек и со значениями любых типов. | ||
+ | * Примеры: <sxh qsp> | ||
+ | n = ARRSIZE('a') | ||
+ | n = ARRSIZE('$a') | ||
+ | !Результат будет одинаковый | ||
+ | </sxh> | ||
+ | * ''**ARRTYPE(**[$имя_переменной], [индекс]**)**'' - получает тип значения, которое хранится в массиве ''%%[$имя_переменной]%%'' под индексом ''[индекс]''. | ||
+ | * Параметр ''%%[индекс]%%'' может отсутствовать, при этом он принимается равным ''0''. То есть вычисляется тип значения переменной/нулевой ячейки массива. Индекс может быть любого типа. | ||
+ | * Функция возвращает одно из следующих значений в зависимости от типа: | ||
+ | * ''%%''%%'' (пустая строка) - элемент массива не задан. | ||
+ | * ''%%'#'%%'' - элемент содержит число. | ||
+ | * ''%%'$'%%'' - элемент содержит строку. | ||
+ | * ''%%'%'%%'' - элемент содержит кортеж. | ||
+ | * Пример: <sxh qsp> | ||
+ | $ddd = 'text' | ||
+ | arrtype('ddd') & ! '$' | ||
+ | $g = 'text' & g = 13 | ||
+ | arrtype('g') & ! '#' | ||
- | ! Вывод данных массива | + | %tuple['index'] = [12, 'string'] |
- | i1=0 | + | arrtype('tuple', 'index') & ! '%' |
- | :ПрыгВыводМассива1 | + | |
- | *Nl | + | |
- | i2=0 | + | |
- | :ПрыгВыводМассива2 | + | |
- | DYNAMIC {*P $МассивПеременных}+i1+{['<<i2>>'] +' '} | + | |
- | i2+=1 | + | |
- | if i2<i2_max : Jump 'ПрыгВыводМассива2' | + | |
- | i1+=1 | + | |
- | if i1<i1_max : Jump 'ПрыгВыводМассива1' | + | |
- | + | ||
- | !{ Результат | + | |
- | [0,0] [0,1] [0,2] | + | |
- | [1,0] [1,1] [1,2] | + | |
- | [2,0] [2,1] [2,2] | + | |
- | [3,0] [3,1] [3,2] | + | |
- | [4,0] [4,1] [4,2] | + | |
- | [5,0] [5,1] [5,2] | + | |
- | } | + | |
+ | ! $empty not exist | ||
+ | arrtype('$empty') & ! '' | ||
</sxh> | </sxh> | ||
+ | * ''%%MAX([выр1],[выр2], …)%%'' - возвращает максимальное из значений выражений-аргументов. Если передан один аргумент, то считается, что указано имя массива: <sxh qsp> | ||
+ | MAX('a') &! вернёт максимальное из числовых значений элементов массива "a" | ||
+ | MAX('$b') &! вернёт максимальное из текстовых значений элементов массива "$b" | ||
+ | MAX('%d') &! вернёт максимальный из кортежей в массиве '%d' | ||
+ | </sxh> | ||
+ | * ''%%MIN([выр1],[выр2], …)%%'' - возвращает минимальное из значений выражений-аргументов. Если передан один аргумент, то считается, что указано имя массива: <sxh qsp> | ||
+ | MIN('a') &! вернёт минимальное из числовых значений элементов массива "a" | ||
+ | MIN('$b') &! вернёт минимальное из текстовых значений элементов массива "$b" | ||
+ | MIN('%d') &! вернёт минимальный из кортежей в массиве '%d' | ||
+ | </sxh> | ||
+ | * ''%%ARRCOMP([$имя_массива],[$шаблон],[#начало])%%'' - возвращает номер элемента массива ''%%[$имя_массива]%%'', соответствующего регулярному выражению ''%%[$шаблон]%%''. Поиск начинается с элемента с номером ''%%[#начало]%%''; индексация элементов массива ведётся с нуля. Если указанное значение не найдено, функция возвращает ''%%-1%%''. | ||
+ | * Поиск работает только по текстовым массивам (символ ''%%$%%'' в названии массива можно опустить). | ||
+ | * Параметр ''%%[#начало]%%'' может отсутствовать, при этом он принимается равным ''%%0%%''. | ||
+ | * Примеры: <sxh qsp> | ||
+ | !Поиск строки 'This' среди элементов массива "$A" | ||
+ | ARRCOMP('$A','This',0) | ||
+ | !'Поиск строки, соответствующей регулярному выражению "abc\d+" | ||
+ | (первые два элемента массива игнорируются)' | ||
+ | ARRCOMP('$A','abc\d+',2) | ||
+ | !'аналогично предыдущему примеру, но поиск осуществляется | ||
+ | по всем элементам массива' | ||
+ | ARRCOMP('$A','.*string.*',0) | ||
+ | ARRCOMP('$A','This') &! эквивалентно 1му варианту | ||
+ | </sxh> | ||
+ | * Функция возвращает только числовой индекс элемента. Строковый или многомерный индекс с помощью данной функции получить нельзя. | ||
+ | Так же см. ARRPACK и UNPACKARR в разделе [[help:tuples|"Кортежи"]] | ||
- | ---- | ||
[[help:strings|Вперёд: Строки]] | [[help:strings|Вперёд: Строки]] | ||
+ |