Question

I have a key => value table I'd like to sort in Lua. The keys are all integers, but aren't consecutive (and have meaning). Lua's only sort function appears to be table.sort, which treats tables as simple arrays, discarding the original keys and their association with particular items. Instead, I'd essentially like to be able to use PHP's asort() function.

What I have:

items = {
    [1004] = "foo",
    [1234] = "bar",
    [3188] = "baz",
    [7007] = "quux",
}

What I want after the sort operation:

items = {
    [1234] = "bar",
    [3188] = "baz",
    [1004] = "foo",
    [7007] = "quux",
}

Any ideas?

Edit: Based on answers, I'm going to assume that it's simply an odd quirk of the particular embedded Lua interpreter I'm working with, but in all of my tests, pairs() always returns table items in the order in which they were added to the table. (i.e. the two above declarations would iterate differently).

Unfortunately, because that isn't normal behavior, it looks like I can't get what I need; Lua doesn't have the necessary tools built-in (of course) and the embedded environment is too limited for me to work around it.

Still, thanks for your help, all!

Was it helpful?

Solution

You seem to misunderstand something. What you have here is a associative array. Associative arrays have no explicit order on them, e.g. it's only the internal representation (usually sorted) that orders them.

In short -- in Lua, both of the arrays you posted are the same.

What you would want instead, is such a representation:

items = {
    {1004, "foo"},
    {1234, "bar"},
    {3188, "baz"},
    {7007, "quux"},
}

While you can't get them by index now (they are indexed 1, 2, 3, 4, but you can create another index array), you can sort them using table.sort.

A sorting function would be then:

function compare(a,b)
  return a[1] < b[1]
end

table.sort(items, compare)

OTHER TIPS

As Komel said, you're dealing with associative arrays, which have no guaranteed ordering.

If you want key ordering based on its associated value while also preserving associative array functionality, you can do something like this:

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 is {1234,3188,1004,7007}, and you can access your data like so:

for _, key in ipairs(sortedKeys) do
  print(key, items[key])
end

result:

1234     bar     
3188     baz     
1004     foo     
7007     quux    

hmm, missed the part about not being able to control the iteration. there

But in lua there is usually always a way.

http://lua-users.org/wiki/OrderedAssociativeTable

Thats a start. Now you would need to replace the pairs() that the library uses. That could be a simples as pairs=my_pairs. You could then use the solution in the link above

PHP arrays are different from Lua tables.

  • A PHP array may have an ordered list of key-value pairs.

  • A Lua table always contains an unordered set of key-value pairs.

A Lua table acts as an array when a programmer chooses to use integers 1, 2, 3, ... as keys. The language syntax and standard library functions, like table.sort offer special support for tables with consecutive-integer keys.

So, if you want to emulate a PHP array, you'll have to represent it using list of key-value pairs, which is really a table of tables, but it's more helpful to think of it as a list of key-value pairs. Pass a custom "less-than" function to table.sort and you'll be all set.

N.B. Lua allows you to mix consecutive-integer keys with any other kinds of keys in the same table—and the representation is efficient. I use this feature sometimes, usually to tag an array with a few pieces of metadata.

Coming to this a few months later, with the same query. The recommended answer seemed to pinpoint the gap between what was required and how this looks in LUA, but it didn't get me what I was after exactly :- which was a Hash sorted by Key.

The first three functions on this page DID however : http://lua-users.org/wiki/SortedIteration

I did a brief bit of Lua coding a couple of years ago but I'm no longer fluent in it.

When faced with a similar problem, I copied my array to another array with keys and values reversed, then used sort on the new array.

I wasn't aware of a possibility to sort the array using the method Kornel Kisielewicz recommends.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top