Ассоциативная сортировка таблицы по значению в Lua

StackOverflow https://stackoverflow.com/questions/2038418

  •  19-09-2019
  •  | 
  •  

Вопрос

У меня есть таблица 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 в новом массиве.

Я не знал о возможности отсортировать массив с помощью метода, рекомендованного Корнелем Киселевичем.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top