2

I am a hobbyest making mods in TableTop Simulator using LUA and have a question that I can not seam to work out.

I have a number of "objects" which is a table in TTS that contains various data for those objects. For example.. obj.position = {x,y,z}... and can be accessed at the axis level as well.

obj.position = {5,10,15} -- x,y,z
obj.position.x == 5

This is an example. The makers of TTS have made it so you can access all the parts like that. So I can acess the object.. and then its various parts. There is a heap, like name, mesh, difuse and a ton more. roations{x,y,z} etc etc

Anyway. I have a table of objects... and would like to order those objects based on the positional data of the x axis.. so highest to lowest. So if I have a table and obj1 in that table is x=3 and obj2 is x=1 and obj3 = x=2 it would be sorted as obj2,obj3,obj1

Pseudo code:

tableOfObjects = {obj1,obj2,obj3}
--[[
tableOfObjectsp[1] == obj1
tableOfObjectsp[2] == obj2
tableOfObjectsp[3] == obj3

tableOfObjectsp[1].position.x == 3
tableOfObjectsp[2].position.x == 1
tableOfObjectsp[4].position.x == 2
--]]
---After Sort it would look this list
tableOfObjects = {obj1,obj3,obj2}
    --[[
tableOfObjectsp[1] == obj1
tableOfObjectsp[2] == obj3
tableOfObjectsp[3] == obj2

tableOfObjectsp[1].position.x == 3
tableOfObjectsp[2].position.x == 2
tableOfObjectsp[3].position.x == 1
--]]

I hope I am making sense. I am self taught in the last few months!

So basically I have a table of objects and want to sort the objects in that table based on a single value attached to each individual object in the table. In this case the obj.position.x

Thanks!

ikegami
  • 367,544
  • 15
  • 269
  • 518
aJynks
  • 677
  • 2
  • 14
  • 27
  • Let me get this strait, you want the max value out of {obj1, obj2, obj3} to be the first index in the table, and the min value to be last? – mike bayko Jul 25 '17 at 01:52
  • I would like to order the objects in the table from table[1]-> end based on the position.x of each object. So if the positions of the x axis in the world space would be like... 3,2,1,0,-1,-2,-3 – aJynks Jul 25 '17 at 02:27

3 Answers3

3

You need table.sort. The first argument is the table to sort, the second is a function to compare items.

Example:

t = {
    {str = 42, dex = 10, wis = 100},
    {str = 18, dex = 30, wis = 5}
}

table.sort(t, function (k1, k2)
    return k1.str < k2.str
end)

This article has more information

Milo Christiansen
  • 3,204
  • 2
  • 23
  • 36
0
table.sort(tableOfObjects, function(a, b) return a.position.x > b.position.x end)

This line will sort your table tableOfObjects in descending order by the x-coordinate.

To reverse order, replace > by <.

From the Lua reference manual:

table.sort (list [, comp])

Sorts list elements in a given order, in-place, from list[1] to list[#list]. If comp is given, then it must be a function that receives two list elements and returns true when the first element must come before the second in the final order (so that, after the sort, i < j implies not comp(list[j],list[i])). If comp is not given, then the standard Lua operator < is used instead.

Note that the comp function must define a strict partial order over the elements in the list; that is, it must be asymmetric and transitive. Otherwise, no valid sort may be possible.

The sort algorithm is not stable: elements considered equal by the given order may have their relative positions changed by the sort.

So in other words table.sort will sort a table in ascending order by its values. If you want to order descending or by something other than the table value (like the x-coordinate of your table value's position in your case) you have to provide a function that tells Lua which element will come first.

Piglet
  • 27,501
  • 3
  • 20
  • 43
-3

you can create a function that handles this exact thing:

local function fix_table(t)
    local x_data = {};
    local inds = {};
    local rt = {};
    for i = 1, #t do
        x_data[#x_data + 1] = t[i].position.x;
        inds[t[i].position.x] = t[i];
    end
    local min_index = math.min(table.unpack(x_data));
    local max_index = math.max(table.unpack(x_data));
    for i = min_index, max_index do
        if inds[i] ~= nil then
            rt[#rt + 1] = inds[i];
        end
    end
    return rt;
end
local mytable = {obj1, obj2, obj3};
mytable = fix_table(mytable);

fix_table first takes in every x value inside of the given table, and also places a new index inside the table inds according to each x value (so that they will be ordered from least to greatest), then it gets the smallest value in the x_data array table, which is used to traverse the inds table in order. fix_table checks to make sure that inds[i] is not equal to nil before it increases the size of the return table rt so that every value in rt is ordered from greatest to least, starting at index 1, and ending at index #rt, finally rt is returned.

I hope this helped.

mike bayko
  • 375
  • 5
  • 20
  • why not simply use `table.sort`? – Piglet Jul 25 '17 at 07:02
  • also using '#inds' in a table and then checking `if inds[i] ~= nil` doesn't make any sense as you cannot reach a nil-value using `#inds`. `unpack` is deprecated. use `table.unpack` instead – Piglet Jul 25 '17 at 07:56
  • @Piglet I use Lua 5.1 – mike bayko Jul 25 '17 at 17:10
  • @Piglet, I beg to differ, imagine if obj3.position.x was some crazy number far apart from the other x values, then trying to index everything in between obj3.position.x and the last valid index would return nil, in which case if I did not check `if inds[i] == nil` then I would be trying to index a nil value, and thus an error would occur and the thread would halt. Remember I am iterating from the lowest index to the highest index. And if `#inds` doesn't cut it then the highest index would simply be `math.max(unpack(x_data));` :) – mike bayko Jul 25 '17 at 17:23