I learned that, for C array of structs, I can just use qsort in stdlib through ffi.
Code: Select all
local ffi = require "ffi"
ffi.cdef[[
void qsort(void *base, size_t, size_t, int (*)(void *, void *));
typedef struct { unsigned int id; unsigned char age, height, weight; } row;
]]
local n = 4 -- number of DB items
local size = ffi.sizeof("row") -- needed byte size for item
local db = ffi.cast("row*", love.data.newByteData(size*n):getFFIPointer())
db[0].id, db[0].age, db[0].height, db[0].weight = 1, 32, 175, 70
db[1].id, db[1].age, db[1].height, db[1].weight = 2, 24, 182, 82
db[2].id, db[2].age, db[2].height, db[2].weight = 3, 42, 152, 58
db[3].id, db[3].age, db[3].height, db[3].weight = 100, 62, 168, 72
local function comp_age(a, b) return a.age - b.age end
local function comp_height(a, b) return a.height - b.height end
local function comp_weight(a, b) return a.weight - b.weight end
local function show()
for i=0, n-1 do
local row = db[i]
print(row.id, " | ", row.age.." yo", " | ", row.height.." cm", " | ", row.weight.." kg")
end
print(string.rep("=", 20))
end
show()
ffi.C.qsort(db, n, size, ffi.cast("int (*) (row*, row*)", comp_age)); show()
ffi.C.qsort(db, n, size, ffi.cast("int (*) (row*, row*)", comp_height)); show()
ffi.C.qsort(db, n, size, ffi.cast("int (*) (row*, row*)", comp_weight)); show()
I'm not familiar with C - so some of this code might be incorrect/unsafe (correction will be appreciated!), but it is showing desired result.
For column-based 2d array in lua, I still couldn't find any ready-made solution. So, as marclurr suggested, I should probably code cutstom quick sort function, that swaps values in other fields simultaneously. In that way, cloning table or tracking ID won't be necessary.
--------
Another advantage of column-based array is that, as values of a field is all of same data type, you can use specific container for each different fields. For text and complex data, we use lua table to hold strings and various objects; but for coordinates and simple values, we can use C array of char/bool/int. Other than slight advantages in memory, reading/writing in C array is noticeablely faster (with JIT on) and data serialization is simpler(saved file is also smaller).
For some cases, being able to selectively loading/saving needed fields of database is also useful.
--------
Alas, there's no table.new - wish you could do that. Maybe you're thinking about Luau's table.create?
No, I was referring to table.new function in luajit extension, which can also be used in love. What I tried to tell was :
Code: Select all
require "table.new"
newDB = {Age = table.new(n, 0), Height = table.new(n, 0), ...} -- n is number of items in db