i have this table
animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324
}
there i can search by a listed entry
for _,v in pairs(animals) do
if v.sname == "bunny" then
print(v.sname, v.name, v.size, v.size2, v.size3)
break
end
end
and get the result:
bunny bunny hase 4 8 9
Now i want to search in my table by starting with a single Letter, for example "b", that show me all the entries starting with the letter "b" to get the same result?
I found no Solution. May you can help me?
First: The table animals needs a trailing } ;-)
Put it in a Lua -i console and play around with...
>animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
}
-- Now set a __call metamethod on same table
>setmetatable(animals,{__call=function(tab,...)
local args={...}
for key, value in pairs(tab) do
if value.sname:find(args[1],1) then print(key,'=',value.sname) end
end
end})
table: 0x565c4a00
-- Lets try it once
>animals('b')
1 = bunny
-- Next one
>animals('c')
3 = cow
-- Last one
>animals('m')
2 = mouse
Using metatables holds your stuff together.
Another fine place is the __index metamethod that can hold all functions you need for that table and can be used like the string functions on a string.
( Like: value.sname:find(args[1],1) )
This leads to the heart of what find should do.
In first example it looks in whole sname for a matching pattern.
Check the Lua patterns what also can be useful.
Maybe a ^ only for the begining sounds smart?
So construct the find pattern: '^'..args[1]
...and use more than one letter if you have a cow, crow, frog and fish in your animals.
Example with function name find in __index
>animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
}
-- Place a find function into __index
>setmetatable(animals,{__index={find=function(tab,...)
local args={...}
for key, value in pairs(tab) do
if value.sname:find('^'..args[1]) then print(key,'=',value.sname) end
end
end}})
table: 0x565c3db0
-- first
>animals:find('c')
3 = cow
-- next
>animals:find('m')
2 = mouse
-- last
>animals:find('b')
1 = bunny
If you like to print all key values then extend the print() in find().
Stop, i found an issue....
Look here - i prefer the first solution:
animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
}
-- Now set a __call metamethod on same table
setmetatable(animals,{__call=function(tab,...)
local args={...}
for v,k in pairs(tab) do
if k.sname:find(args[1],1) then print(v,'=',k.sname) end
end
end})
-- Search Entries with Start U.....
-- there should be no result, but....
animals('u')
i get the Result:
1 = bunny
2 = mouse
that should not be the result!
Related
I need a little help here
Let's suppose I have a table with numbers.
tbl = {'item1' = 6, 'item2' = 1, 'item3' = 6, 'item4' = 3, 'item5' = 2, 'item5' = 3}
I wanna put all repeated numbers in the same table (with key and value) like this:
repeated = {'item1' = 6, 'item3' = 6, 'item4' = 3, 'item5' = 3}
and creat a new one with the "not repeated" numbers:
notrepeated = {'item2' = 1, 'item5' = 2}
Can someone help? Thank you so much.
-- Count the items for each number
local itemsByNum = {}
for item, num in pairs(tbl) do
itemsByNum[num] = (itemsByNum[num] or 0) + 1
end
-- Now move objects to the respective tables
local rep, noRep = {}, {} -- can't use "repeat" as that's a Lua keyword
for item, num in pairs(tbl) do
if itemsByNum[num] > 1 then -- repeated at least once
rep[item] = num
else -- unique number
norep[item] = num
end
end
I would like to create a flowchart using the DiagrammeR nodes and edges functionality with R instead of using the graphviz wrapper function.
However, I can't figure out how to make the edges straight to make it nice.
This is the graphviz solution that looks like what I want:
# Packages needed for the test
library(DiagrammeR)
# grViz solution
grViz("digraph flowchart {
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle]
tab1 [label = '##1', group=gr1]
tab2 [label = '##2', group=gr2]
tab3 [label = '##3', group=gr3]
invis1 [style = invis, shape=point, width = 0, group=gr1]
invis1a [style = invis, shape=point, width = 0, group=gr2]
invis1b [style = invis, shape=point, width = 0, group=gr3]
# edge definitions with the node IDs
edge [arrowhead='none']
tab1 -> invis1;
invis1a -> invis1 -> invis1b; {rank=same invis1a invis1 invis1b}
edge [arrowhead='normal']
invis1a -> tab2;
invis1b -> tab3; {rank=same tab2 tab3}}
[1]: 'A'
[2]: 'B'
[3]: 'C'
")
This is my attempt to recreate the same graph with the nodes and edges solution:
# Packages needed for the test
library(DiagrammeR)
library(magrittr)
# Node and edge df solution
create_graph() %>%
add_node( # id 1
label = "A",
type = "group_1",
node_aes = node_aes(
style = "filled",
shape = "rectangle",
fixedsize = FALSE)
) %>%
add_node( # id 2
type = "group_1",
node_aes = node_aes(
style = "invisible",
height = 0,
width = 0)
) %>%
add_edge(
from = 1,
to = 2,
edge_aes = edge_aes(
arrowhead = "none")
) %>%
add_node( # id 3
type = "group_2",
node_aes = node_aes(
style = "invisible",
height = 0,
width = 0)
) %>%
add_edge(
from = 2,
to = 3,
edge_aes = edge_aes(
arrowhead = "none")
) %>%
add_node( # id 4
type = "group_3",
node_aes = node_aes(
style = "invisible",
height = 0,
width = 0)
) %>%
add_edge(
from = 2,
to = 4,
edge_aes = edge_aes(
arrowhead = "none")
) %>%
add_node( # id 5
label = "B",
type = "group_2",
node_aes = node_aes(
style = "filled",
shape = "rectangle",
fixedsize = FALSE)
) %>%
add_edge(
from = 3,
to = 5,
edge_aes = edge_aes(
arrowhead = "normal")
) %>%
add_node( # id 6
label = "C",
type = "group_3",
node_aes = node_aes(
style = "filled",
shape = "rectangle",
fixedsize = FALSE)
) %>%
add_edge(
from = 4,
to = 6,
edge_aes = edge_aes(
arrowhead = "normal")
) %>%
render_graph()
I am inserting into a table like this
Admin = {}
table.insert(Admins, {id = playerId, Count = 0})
And that works fine.
How do I remove that specific admin from that table now?
The following does not work, and Im sure its because ID is stored in an array that's inside of the table, but how would I access that then?
table.remove(Admins, playerId)
Basically,
I want to remove from the table Admins, where the ID == playerId that I input.
There are two approaches to remove an entry from the table, both are acceptable ways:
1. myTable[index] = nil Removes an entry from given index, but adds a hole in the table by maintaining the indices
local Admins = {}
table.insert(Admins, {id = 10, Count = 0})
table.insert(Admins, {id = 20, Count = 1})
table.insert(Admins, {id = 30, Count = 2})
table.insert(Admins, {id = 40, Count = 3})
local function removebyKey(tab, val)
for i, v in ipairs (tab) do
if (v.id == val) then
tab[i] = nil
end
end
end
-- Before
-- [1] = {['Count'] = 0, ['id'] = 10},
-- [2] = {['Count'] = 1, ['id'] = 20},
-- [3] = {['Count'] = 2, ['id'] = 30},
-- [4] = {['Count'] = 3, ['id'] = 40}}
removebyKey(Admins, 20)
-- After
-- [1] = {['Count'] = 0, ['id'] = 10},
-- [3] = {['Count'] = 2, ['id'] = 30},
-- [4] = {['Count'] = 3, ['id'] = 40}
2. table.remove(myTable, index)
Removes the entry from given index and renumbering the indices
local function getIndex(tab, val)
local index = nil
for i, v in ipairs (tab) do
if (v.id == val) then
index = i
end
end
return index
end
local idx = getIndex(Admins, 20) -- id = 20 found at idx = 2
if idx == nil then
print("Key does not exist")
else
table.remove(Admins, idx) -- remove Table[2] and shift remaining entries
end
-- Before is same as above
-- After entry is removed. Table indices are changed
-- [1] = {['id'] = 10, ['Count'] = 0},
-- [2] = {['id'] = 30, ['Count'] = 2},
-- [3] = {['id'] = 40, ['Count'] = 3}
bestSword = {
{name = 'www' , lvl = 35, atk = 38, npcPrice = 15000 , buyPrice = 0},
{name = 'bbb' , lvl = 40, atk = 40, npcPrice = 20000 , buyPrice = 0},
{name = 'eee' , lvl = 50, atk = 42, npcPrice = 25000 , buyPrice = 0},
{name = 'sss' , lvl = 55, atk = 43, npcPrice = 30000 , buyPrice = 0},
{name = 'aaa' , lvl = 60, atk = 44, npcPrice = 30000 , buyPrice = 0},
{name = 'qwe' , lvl = 70, atk = 46, npcPrice = 35000 , buyPrice = 0},
{name = 'asd' , lvl = 82, atk = 48, npcPrice = 60000 , buyPrice = 0}
}
I have this table, how can I iterate from last index to first? It should break depends from lvl. I just want to show this table from the best weapon. For example if Player have level 53, then I want to show only weapons for his lvl or lower. I need to show that from the best one (at top) its why I want to iterate from the last index. Could someone help?
EDIT:
Thanks for help. There is still a problem that I need this changed table later. It shows all fine but I need to buy all litems from this (changed) list later. So I must replace in some way this 2 tables. Is there any easy way to do that? I tried to remove elements from this table but it still not works.
Or its possible to make some map in Lua? It must be dynamic sized so i cant use table i guess. Something with key - value
A numeric for loop, counting down, is the best option:
local t = {2,4,6,8}
for i = #t, 1, -1 do
print(t[i])
end
Assuming that the table is not necessarily sorted into level order (unlike the example), we need to do two things:
Find which swords are in the level range
Sort them into descending order
Now the first one in the temporary table is the "best" sword.
Like this:
bestSword = {
{name = 'www' , lvl = 35, atk = 38, npcPrice = 15000 , buyPrice = 0},
{name = 'bbb' , lvl = 40, atk = 40, npcPrice = 20000 , buyPrice = 0},
{name = 'eee' , lvl = 50, atk = 42, npcPrice = 25000 , buyPrice = 0},
{name = 'sss' , lvl = 55, atk = 43, npcPrice = 30000 , buyPrice = 0},
{name = 'aaa' , lvl = 60, atk = 44, npcPrice = 30000 , buyPrice = 0},
{name = 'qwe' , lvl = 70, atk = 46, npcPrice = 35000 , buyPrice = 0},
{name = 'asd' , lvl = 82, atk = 48, npcPrice = 60000 , buyPrice = 0}
}
myLevel = 53 -- wanted level
-- temporary table
possible = { }
-- extract ones which are in range
for k, v in ipairs (bestSword) do
if v.lvl <= myLevel then
table.insert (possible, v)
end -- if
end -- for
if #possible == 0 then
print "No matching swords"
else
table.sort (possible, function (a, b) return a.atk > b.atk end )
bestSword = possible [1]
print ("Best sword is", bestSword.name, "lvl =", bestSword.lvl,
"atk = ", bestSword.atk)
end -- if
Or its possible to make some map in Lua? It must be dynamic sized so i cant use table i guess. Something with key - value
Tables in Lua are maps. Every table has key/value pairs. The one you are using there are simply numerically-keyed tables.
All tables are dynamically sized.
T = {
{Name = "Mark", HP = 54, Breed = "Ghost"},
{Name = "Stan", HP = 24, Breed = "Zombie"},
{Name = "Juli", HP = 100, Breed = "Human"}},
Questions:
How would I Print just the names?
and
How can I sort it by HP?
You need to iterate over the table by using either the pairs or ipairs function to print the name. ipairs iterates from 1 to N (numeric indices only), while pairs iterates over every element, in no defined order.
> T = { {Name = "Mark", HP = 54, Breed = "Ghost"}, {Name = "Stan", HP = 24, Breed = "Zombie"}, {Name = "Juli", HP = 100, Breed = "Human"}}
> for _,t in ipairs(T) do print(t.Name) end
Mark
Stan
Juli
Then you can use the table.sort function to sort the table in-place:
> table.sort(T, function(x,y) return x.HP < y.HP end)
> for _,t in ipairs(T) do print(t.Name, t.HP) end
Stan 24
Mark 54
Juli 100
The second argument to table.sort is a comparison function of your choice; in this case, we only wanted to compare the HP values.