Ассоциативная сортировка таблицы по значению в Lua
Вопрос
У меня есть таблица key => value, которую я хотел бы отсортировать в Lua.Все ключи являются целыми числами, но не являются последовательными (и имеют значение).Единственной функцией сортировки Lua, по-видимому, является table.sort
, который обрабатывает таблицы как простые массивы, отбрасывая исходные ключи и их связь с определенными элементами.Вместо этого я бы, по сути, хотел иметь возможность использовать PHP- это asort()
функция.
То, что у меня есть:
items = {
[1004] = "foo",
[1234] = "bar",
[3188] = "baz",
[7007] = "quux",
}
Что я хочу после операции сортировки:
items = {
[1234] = "bar",
[3188] = "baz",
[1004] = "foo",
[7007] = "quux",
}
Есть какие-нибудь идеи?
Редактировать: Основываясь на ответах, я собираюсь предположить, что это просто странная особенность конкретного встроенного интерпретатора Lua, с которым я работаю, но во всех моих тестах, pairs()
всегда возвращает элементы таблицы в том порядке, в котором они были добавлены в таблицу.(т.е.два приведенных выше объявления будут повторяться по-разному).
К сожалению, поскольку это ненормальное поведение, похоже, я не могу получить то, что мне нужно;Lua не имеет встроенных необходимых инструментов (конечно), а встроенная среда слишком ограничена, чтобы я мог обойти ее.
Тем не менее, всем спасибо за вашу помощь!
Решение
Кажется, вы чего-то не так поняли.То, что у вас здесь есть, - это ассоциативный массив.Ассоциативные массивы не имеют явного порядка в них, напримерэто только внутреннее представление (обычно отсортированное) упорядочивает их.
Короче говоря, в Lua оба опубликованных вами массива являются тот же самый.
То, что вы хотели бы получить вместо этого, - это такое представление:
items = {
{1004, "foo"},
{1234, "bar"},
{3188, "baz"},
{7007, "quux"},
}
Хотя сейчас вы не можете получить их по индексу (они проиндексированы 1, 2, 3, 4, но вы может создайте еще один индексный массив), вы можете отсортировать их с помощью table.sort
.
Тогда функция сортировки была бы:
function compare(a,b)
return a[1] < b[1]
end
table.sort(items, compare)
Другие советы
Как сказал Комель, вы имеете дело с ассоциативными массивами, которые не имеют гарантированного порядка.
Если вы хотите упорядочить ключи на основе связанного с ними значения, сохраняя при этом функциональность ассоциативного массива, вы можете сделать что-то вроде этого:
function getKeysSortedByValue(tbl, sortFunction)
local keys = {}
for key in pairs(tbl) do
table.insert(keys, key)
end
table.sort(keys, function(a, b)
return sortFunction(tbl[a], tbl[b])
end)
return keys
end
items = {
[1004] = "foo",
[1234] = "bar",
[3188] = "baz",
[7007] = "quux",
}
local sortedKeys = getKeysSortedByValue(items, function(a, b) return a < b end)
sortedKeys - это {1234,3188,1004,7007}, и вы можете получить доступ к своим данным следующим образом:
for _, key in ipairs(sortedKeys) do
print(key, items[key])
end
Результат:
1234 bar
3188 baz
1004 foo
7007 quux
хм, пропустил ту часть, где говорилось о невозможности контролировать итерацию.там
Но в lua обычно всегда есть выход.
http://lua-users.org/wiki/OrderedAssociativeTable
Это только начало.Теперь вам нужно будет заменить pairs(), который использует библиотека.Это может быть простое значение в виде pairs=my_pairs.Затем вы могли бы использовать решение, приведенное по ссылке выше
PHP-массивы отличаются от таблиц Lua.
PHP-массив может содержать упорядоченный список из пар ключ-значение.
Таблица Lua всегда содержит неупорядоченный набор из пар ключ-значение.
Таблица Lua действует как массив, когда программист выбирает использование целых чисел 1, 2, 3, ...как ключи.Синтаксис языка и стандартные библиотечные функции, такие как table.sort
предложите специальную поддержку для таблиц с последовательными целочисленными ключами.
Итак, если вы хотите эмулировать массив PHP, вам придется представить его с помощью списка пар ключ-значение, который на самом деле является таблицей таблиц, но полезнее думать о нем как о списке пар ключ-значение.Передайте пользовательскую функцию "меньше, чем" в table.sort
и у тебя все будет готово.
Н.Б.Lua позволяет вам смешать последовательные целочисленные ключи с любыми другими типами ключей в то же самое таблица—и представление эффективно.Иногда я использую эту функцию, обычно для пометки массива несколькими фрагментами метаданных.
Обращаюсь к этому несколько месяцев спустя с тем же запросом.Рекомендуемый ответ, казалось, точно указывал на разрыв между тем, что требовалось, и тем, как это выглядит в LUA, но он не дал мне точно того, что мне было нужно: - который был хэшем, отсортированным по ключу.
Однако первые три функции на этой странице выполнялись : http://lua-users.org/wiki/SortedIteration
Пару лет назад я немного поработал с кодированием Lua, но больше не владею им свободно.
Столкнувшись с аналогичной проблемой, я скопировал свой массив в другой массив с обратными ключами и значениями, а затем использовал sort
в новом массиве.
Я не знал о возможности отсортировать массив с помощью метода, рекомендованного Корнелем Киселевичем.