Ассоциативная сортировка таблицы по значению в Lua - PullRequest
20 голосов
/ 10 января 2010

У меня есть таблица ключей => значений, которую я хочу отсортировать в 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 не имеет необходимых встроенных инструментов (конечно), а встроенная среда слишком ограничена, чтобы я мог ее обойти.

Тем не менее, спасибо за помощь, все!

Ответы [ 6 ]

36 голосов
/ 10 января 2010

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

Короче говоря - в 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)
8 голосов
/ 04 июля 2014

Как сказал Комел, вы имеете дело с ассоциативными массивами, у которых нет гарантированного упорядочения.

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

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    
6 голосов
/ 10 января 2010

хмм, пропустил часть о невозможности контролировать итерацию. есть

Но в Луа всегда есть выход.

http://lua -users.org / вики / OrderedAssociativeTable

Это начало. Теперь вам нужно будет заменить пары (), которые использует библиотека. Это может быть просто как пары = my_pairs. Затем вы можете использовать решение по ссылке выше

3 голосов
/ 12 мая 2011

Приходя к этому через несколько месяцев, с тем же запросом. Рекомендованный ответ, казалось, точно определил разрыв между тем, что требовалось, и тем, как это выглядит в LUA, но он не дал мне того, что мне было нужно: - это был хэш, отсортированный по ключу.

Первые три функции на этой странице ДЕЙСТВИТЕЛЬНО, однако: http://lua -users.org / wiki / SortedIteration

3 голосов
/ 11 января 2010

Массивы PHP отличаются от таблиц Lua.

  • Массив PHP может иметь упорядоченный список пар ключ-значение.

  • Таблица Lua всегда содержит неупорядоченный набор пар ключ-значение.

Таблица Lua действует как массив, когда программист решает использовать целые числа 1, 2, 3, ... в качестве ключей. Синтаксис языка и стандартные библиотечные функции, такие как table.sort, предлагают специальную поддержку для таблиц с последовательными целочисленными ключами.

Итак, если вы хотите эмулировать массив PHP, вам придется представлять его с помощью списка пар ключ-значение, который на самом деле представляет собой таблицу таблиц, но более полезно рассматривать его как список ключей. пары Передайте пользовательскую функцию «меньше чем» на table.sort, и все будет готово.

N.B. Lua позволяет вам смешивать последовательных целочисленных ключей с любыми другими типами ключей в той же таблице & mdash; и представление эффективно. Иногда я использую эту функцию, обычно для пометки массива несколькими метаданными.

1 голос
/ 10 января 2010

Пару лет назад я написал небольшую часть кода на Lua, но я больше не владею им.

Столкнувшись с подобной проблемой, я скопировал свой массив в другой массив с обратными ключами и значениями, а затем использовал sort в новом массиве.

Я не знал о возможности сортировки массива, используя метод, который рекомендует Kornel Kisielewicz.

...