Кодирование - Таблицы

## Что такое таблицы?

Таблицы - это переменные, которые позволяют хранить в них несколько значений, подобно контейнеру. Таблицы предоставляют вам возможность сопоставлять значения с определенными ключами, подобно тому, как словарь сопоставляет определения (значения) с конкретными словами (ключами).

Исходя из примера со словарем, можно найти любое слово в любом словаре и получить его определение взамен, таким же образом, как можно найти ключ в таблице и извлечь значение, хранящееся в этом ключе или на нем.

Имейте в виду, что это чрезвычайно простое объяснение, и в таблицах действительно содержится гораздо больше, чем описано здесь.

### Ключи

Как упоминалось выше, таблицы в Lua содержат ключи и значения; ключи являются идентификаторами значений и известны как "индекс" любой записи.

Можно было бы использовать ключи несколькими способами. Во-первых, ключи могут быть числовыми и/или представлять порядок вещей, т.е.:

```
[1]
[2]
[3]
[4]
[5]
-- и так далее...

```
Ключи также могут быть строками, такими как:

```
["Строка1"]
["Еще одна"]
["И еще одна"]
-- и так далее...

```
Когда ключи используются для представления порядка вещей, они позволяют таблице функционировать больше как списку или даже массиву объектов на других языках - ключи являются числовыми и последовательными (по порядку). Когда строки (или другие типы) используются в качестве ключей, таблицы можно использовать скорее как словарь или объект хэш-карты. Лучшая часть всего этого заключается в том, что таблицы в Lua могут использовать оба этих вида "режимов" одновременно!

Однако в качестве ключей можно использовать не только цифры или строки. Согласно официальной Вики пользователей Lua, ключами могут быть переменные любого типа, кроме nil. Однако чаще всего они обычно определяются либо как числа, либо как строки.

Для каждого ключа в таблице может быть только одно значение - ключи должны быть уникальными. Единственный способ сохранить более одного значения для определенного ключа - это использовать в качестве значения новую таблицу. (Однако технически это все еще только одно значение - таблица считается одним значением, но внутри нее могут храниться другие данные. Этот сценарий "таблица внутри таблицы" называется "вложенной" таблицей.)

### Значения

Значения могут быть любого типа данных - даже других таблиц!

### Пример создания таблицы

```
-- Здесь мы создаем пустую таблицу с помощью "конструктора таблиц". ( {} )
emptyTable = {}

-- Мы можем создать таблицу с предопределенными значениями:
table1 = {
    [1] = "Первый",
    [2] = "Второй",
}
-- (Не забудьте поставить запятую после каждой строки 'ключ = значение'.)

-- Мы также можем заставить Lua автоматически заполнять числовые значения "порядка":
table1 = { "Первый", "Второй" }
-- table1 будет содержать [1] = Первый и [2] = второй.

-- Мы можем определить строковые ключи в нашей таблице двумя различными способами:
-- Во-первых, сокращенный способ:
table1.SomeStringKey = "Привет!"
-- или, долгий путь:
table1["SomeStringKey"] = "Привет!"

-- Чтобы устно описать оба этих метода, мы могли бы сказать:
-- "table1() В SomeStringKey РАВНО Привет!"

```

### Зацикливание на таблице

Есть несколько способов перебрать все пары ключ/значение в таблице. Используемый вами метод будет зависеть от того, как расположены ключи.

Если Lua автоматически заполнила ваши числовые ключи "порядка", как в последнем примере, вы можете использовать цикл **for**, чтобы просто перебирать таблицу.

Если есть какие-либо ключи, которые не были определены как числовые ключи "порядка", то есть строковые ключи, или если вы определили числовой ключ "не по порядку", вам придется использовать **pairs**() для перебора таблицы.

**pairs** будет выполнять цикл по всем значениям в таблице, включая числовые ключи / ключи порядка И ключи строки (или другого типа); на других языках это похоже на цикл для каждого.

```
-- Давайте переопределим нашу таблицу, используя автоматический метод числового ключа/порядка:
table1 = { "Первый", "Второй", "Третий" }
-- Теперь я возьму ту же таблицу, которую мы только что создали, и определю строковый ключ в таблице.
table1.StringKey = "Четвертый?"
-- Прежде чем поместить StringKey в таблицу, мы могли бы просто использовать forloop, поскольку
-- все ключи были автоматически определены как упорядоченные номера.
-- Однако, поскольку теперь в таблице есть StringKey, нам нужно использовать pairs() для выполнения цикла
-- над таблицей, поскольку forloop не "получит" запись для StringKey.

-- Давайте используем forloop для перебора числовых значений.
-- Переменная 'i' будет действовать как наш ключ, и мы сможем получить соответствующее значение
-- с помощью ссылки 'table1[i]':
for i=1,#table1 do
    print( i .. " == " .. table1[i] )
end
-- Это должно напечатать:
-- 1 == Первый
-- 2 == Второй
-- 3 == Третий

-- ...теперь давайте посмотрим, как это выглядит с парами.
for k,v in pairs( table1 ) do
    -- Внутри цикла пар!
    -- Давайте напечатаем каждый ключ в таблице и соответствующее ему значение.
    print( k .. " == " .. v )
end
-- Это должно напечатать:
-- 1 == Первый
-- 2 == Второй
-- 3 == Третий
-- StringKey == Четвертый?

```

### Использование библиотеки таблиц

Библиотека таблиц - это стандартная библиотека Lua, которая предоставляет функции для управления таблицами. В Garry's Mod в эту библиотеку добавлено несколько дополнительных полезных функций. Вот некоторые примеры функций, определенных в библиотеке таблиц.

#### table.Merge

```
-- Мы определяем стол, полный фруктов,
Fruits = {
    "Яблоко",
    "Апельсин",
    "Банан",
    "Ананас",
}

-- И стол, полный овощей.
Veggies = {
    "Перец",
    "Помидор"
}

-- Мы будем использовать функцию table.Merge для объединения значений в таблице "Овощи" в таблицу "Фрукты".
table.Merge( Fruits, Veggies ) -- аргументы: кому, из
-- Когда это запускается:
-- значение "Перец" из таблицы овощей заменит значение "Яблоко" во фруктах (ключ '1'), и:
-- значение "Помидор" из таблицы овощей заменит значение "Апельсин" во фруктах (клавиша "2").

-- Давайте напечатаем все новые значения в 'Fruits':
print( table.concat(Fruits," ") )

-- Это приведет к выводу:
-- Перец Помидор Банан Ананас

```

#### table.Add

```
-- Опять же, у нас есть свои столы с фруктами и овощами.
Fruits = {
    "Яблоко",
    "Aпельсин"
}

Veggies = {
    "Перец",
    "Помидор"
}

-- Добавьте все значения в овощах в конец таблицы Фрукты:
table.Add(Fruits, Veggies) -- аргументы: кому, из

print( table.concat(Fruits," ") )

-- Это приведет к выводу:
-- Яблоко Апельсин Перец Помидор

```

#### Другие функции таблицы

Вы можете обратиться к странице библиотеки библиотеки таблиц, чтобы ознакомиться со всеми функциями библиотеки таблиц.

### Другие функции

Некоторые другие функции также полезны для таблиц, включая, но не ограничиваясь ими:

#### ipairs

Мы рассмотрели использование **pairs**() в разделе "Зацикливание на таблице". **pairs**() имеет родственную функцию под названием **ipairs**(), которая выполняет точно то же самое, что и **pairs** (перебирает все пары k /v() в таблице), но только для цифровых клавиш.