Sorting Tables - Lua - lua

I am trying to sort but there is a nil. How can i get around this?
Code im useing: (sorting it by name and HPs. in case there is duplicate HPs)
T = { {Name = "Mark", HP = 54, Breed = "Ghost"},
{Name = "Stan", HP = 24, Breed = "Zombie"},
{Name = "Juli", HP = 100, Breed = "Human"},
{ HP = 100, Breed = "Human"}
}
function Sorting(T)
table.sort(T,
function(x,y)
return x.Name < y.Name and x.HP < y.HP
end
)
end

Assuming you want to compare by HP if name isn't available, how about you change the sort comparison function to:
function(x, y)
if x.Name == nil or y.Name == nil then return x.HP < y.HP
else return x.Name < y.Name and x.HP < y.HP
end
end
Your problem is that Name isn't a real key if it's not available all the time.

Related

How to combine two lua tables and maintain their ordering?

Given
local t1 = {
["foo"] = "val1",
["bar"] = "val2",
["baz"] = "val3",
}
local t2 = {
["foo1"] = "val4",
["bar1"] = "val5",
["baz1"] = "val6",
}
Id like to get result
local t3 = {
["foo"] = "val1",
["bar"] = "val2",
["baz"] = "val3",
["foo1"] = "val4",
["bar1"] = "val5",
["baz1"] = "val6",
}
I have been attempting various ways for around a day now, using other questions provided here, and still am unsure of where things are going wrong or how to handle it. The tables vs arrays in lua is a bit hard to grasp. Thanks for any help :D
AFAIK, if the hash part of a table is used, it does not preserve the order. There is a very simple way to highlight this.
t1 = {
["foo"] = "val1",
["bar"] = "val2",
["baz"] = "val3",
}
for k,v in pairs(t1) do
print(k, v)
end
On my computer, the order is not preserved:
foo val1
baz val3
bar val2
If the order is important, it is required to use an array.
One (convoluted) way to do it would be the following code. Obviously, I am not aware of the given requirements, so this code might not be the most straight-forward.
t1 = {
{ foo = "val1" }, -- Element t1[1]
{ bar = "val2" }, -- Element t1[2]
{ baz = "val3" } -- Element t1[3]
}
t2 = {
{ foo1 = "val4" }, -- Element t2[1]
{ bar1 = "val5" }, -- Element t2[2]
{ baz1 = "val6" } -- Element t2[3]
}
function merge (t1, t2)
local new_table = {}
-- Copy all the items from the first table
for index = 1, #t1 do
new_table[#new_table+1] = t1[index]
end
-- Copy all the items from the second table
for index = 1, #t2 do
new_table[#new_table+1] = t2[index]
end
-- return the new table
return new_table
end
for k,v in pairs(merge(t1,t2)) do
local subtable = v
for k,v in pairs(subtable) do
print(k,v)
end
end
This would print the following:
foo val1
bar val2
baz val3
foo1 val4
bar1 val5
baz1 val6

How to implement the exercise 15.5 in pil4?

I am working on this exercise in pil4.
Exercise 15.5:
The approach of avoiding constructors when saving tables with cycles is too radical. It is
possible to save the table in a more pleasant format using constructors for the simple case, and to use
assignments later only to fix sharing and loops. Reimplement the function save (Figure 15.3, “Saving
tables with cycles”) using this approach. Add to it all the goodies that you have implemented in the previous
exercises (indentation, record syntax, and list syntax).
I have tried this with the code below, but it seems not to work on the nested table with a string key.
local function basicSerialize(o)
-- number or string
return string.format("%q",o)
end
local function save(name,value,saved,indentation,isArray)
indentation = indentation or 0
saved = saved or {}
local t = type(value)
local space = string.rep(" ",indentation + 2)
local space2 = string.rep(" ",indentation + 4)
if not isArray then io.write(name," = ") end
if t == "number" or t == "string" or t == "boolean" or t == "nil" then
io.write(basicSerialize(value),"\n")
elseif t == "table" then
if saved[value] then
io.write(saved[value],"\n")
else
if #value > 0 then
if indentation > 0 then io.write(space) end
io.write("{\n")
end
local indexes = {}
for i = 1,#value do
if type(value[i]) ~= "table" then
io.write(space2)
io.write(basicSerialize(value[i]))
else
local fname = string.format("%s[%s]",name,i)
save(fname,value[i],saved,indentation + 2,true)
end
io.write(",\n")
indexes[i] = true
end
if #value > 0 then
if indentation > 0 then io.write(space) end
io.write("}\n")
else
io.write("{}\n")
end
saved[value] = name
for k,v in pairs(value) do
if not indexes[k] then
k = basicSerialize(k)
local fname = string.format("%s[%s]",name,k)
save(fname,v,saved,indentation + 2)
io.write("\n")
end
end
end
else
error("cannot save a " .. t)
end
end
local a = { 1,2,3, {"one","Two"} ,5, {4,b = 4,5,6} ,a = "ddd"}
local b = { k = a[4]}
local t = {}
save("a",a,t)
save("b",b,t)
print()
And I got the wrong ouput.
a = {
1,
2,
3,
{
"one",
"Two",
}
,
5,
{
4,
5,
6,
}
a[6]["b"] = 4
,
}
a["a"] = "ddd"
b = {}
b["k"] = a[4]
How could I make the text ' a[6]["b"] = 4 ' jump out of the table constructor?

Slick 3.0 Multiple Many-To-Many calls

Taking inspiration from this post:
How can I present a many-to-many relationship using a link table with ScalaQuery or SLICK?
My situation is a somewhat the same with some small exception.
def testManyToMany(): Unit = db withSession {
object A extends Table[(Int, String)]("a") {
def id = column[Int]("id", O.PrimaryKey)
def s = column[String]("s")
def * = id ~ s
def bs = AToB.filter(_.aId === id).flatMap(_.bFK)
// note I have another many-to-many join
def cs = AtoC.filter(_cId === id).flatMap(_.aFK)
}
object B extends Table[(Int, String)]("b") {
def id = column[Int]("id", O.PrimaryKey)
def s = column[String]("s")
def * = id ~ s
def as = AToB.filter(_.bId === id).flatMap(_.aFK)
}
object AToB extends Table[(Int, Int)]("a_to_b") {
def aId = column[Int]("a")
def bId = column[Int]("b")
def * = aId ~ bId
def aFK = foreignKey("a_fk", aId, A)(a => a.id)
def bFK = foreignKey("b_fk", bId, B)(b => b.id)
}
object AToC extends Table[(Int, Int)]("a_to_c") {
def aId = column[Int]("a")
def cId = column[Int]("c")
def * = aId ~ cId
def aFK = foreignKey("a_fk", aId, A)(a => a.id)
def cFK = foreignKey("c_fk", cId, C)(c => c.id)
}
}
Now when I want to fetch all A's by id, I would also want to fetch it associations in B and C, I would do something like:
for {
a <- A if a.id >= 2
aToB <- AToB if aToB.aId === a.id
b <- B if b.id === aToB.bId
} yield (a.s, b.s)
How can I include the join to the C table? Is having something like this correct?
for {
a <- A if a.id >= 2
aToB <- AToB if aToB.aId === a.id
aToC <- AToC if aToC.aId === a.id
b <- B if b.id === aToB.bId
c <- C if c.id === aToC.cId
} yield (a.s, b.s)
Wouldn't this try to do a sub-select on aToC for each aToB as this is just a flatMap operation?

How to run table and print a specific key

I have a table:
employee = {
name = "John", age = 30,
name = "George", age = 35
}
Now, I want to run the whole table, and if the name "George" is found, then the appropriate age to be printed. How can I do this? From what I searched I found that you can run a list with the code for k, v in pairs(employee) do but I don't know how to continue from there.
Your table will need to be restructured to start off with.
employee = {
{name = "John", age = 30},
{name = "George", age = 35},
}
This will allow the age to always match up with the name. Then you could run:
for _,v in ipairs(employee) do
if v.name == "George" then
return v.age
end
end
You can even create it as a function so you can check whatever name you want:
function find_age(n)
for _,v in ipairs(employee) do
if v.name == n then
return v.age
end
end
end
Of course, this will return the age of every n in the table, though.
Updated for comment
You can do it with a function as well.
function add_employee(n,a)
table.insert(employee, {name = n, age = a})
end

Sorting Tables Twice in one Function - Lua

Want the function to sort the table by HP but if duplicate HPs then sorts by name. When i run this function it just groups the duplicate HPs together in no order by the name.
T = { {Name = "Mark", HP = 54, Breed = "Ghost"}, {Name = "Stan", HP = 24, Breed = "Zombie"}, {Name = "Juli", HP = 100, Breed = "Human"}, { HP = 100, Breed = "Human"} }
function(x, y) if x.Name == nil or y.Name == nil then return x.HP < y.HP else return x.Name < y.Name and x.HP < y.HP end end) end
Try this sort func:
function(x,y)
if x.Name == nil or y.Name == nil then
return x.HP < y.HP
else
return x.HP < y.HP or (x.HP == y.HP and x.Name < y.Name)
end
end
Since you always want differing HPs to be the primary sorting order (and name secondary), you want the HP check to come first in the or clause so that if it differs it'll skip any other checks and just determine based on HP.

Resources