How i can add to table only max 10 users ?
Because i saving scoretbl in txt, and this file have more 100 lines :/ So i want save only 10 users.
I don't know how can i check there is username in the table, and don't add this user or not this username in the table and add it?
Example:
local scoretbl = {}
local num = 0
for i=1, 10 do
table.insert(scoretbl,{'Name '..i, 100 + num})
num = num + 100
end
local function AddToTable(name, score)
if table.HasValue(scoretbl,name) then return end // hmm its not work ?
table.insert(scoretbl,{name, score})
end
AddToTable('User 55', 5454)// 11 user
AddToTable('User 55', 5454)// check: only one username in table
AddToTable('User 32', 5454)// 12 user
local function ShowOnly10()
table.sort( scoretbl, function( a, b ) return a[2] > b[2] end )
//table.remove(scoretbl,#scoretbl) remove last index in table, if i need only 10 value, i need delete in cycle ?
for k, v in pairs(scoretbl) do
print(k ,v[1], v[2])
end
end
ShowOnly10()
// upd: maybe its fix username ?
local function AddToTable(name, score)
for k, v in pairs(scoretbl) do
if v[1] == name then return false end
end
table.insert(scoretbl,{name, score})
end
I recommend that you make use of Lua's hashtable, v.name and v.score are easier to read than v[1] and v[2].
The function table.HasValue does not exist. You have to write your own.
When you want to print only the first ten elements, you should only iterate over the first ten (or up to the length of the table if it is less than ten elements long).
Line comments in Lua start with --, not //.
local scoretbl = {}
for i = 1,10 do
table.insert(scoretbl, { name = 'Name '..i, score = 100*i })
end
local function AddToTable(name, score)
-- Walk the whole table to find whether a name exists
for i,v in ipairs(scoretbl) do
if v.name == name then
-- if the record is present, update it
scoretbl[i].score = score
return
end
end
-- Insert new record
table.insert(scoretbl, { name = name, score = score })
end
AddToTable('User 55', 5454) -- 11 users
AddToTable('User 55', 5454) -- check: only one username in table
AddToTable('User 32', 5454) -- 12 users
local function ShowOnly10()
table.sort(scoretbl,function(a,b) return a.score > b.score end)
for i = 1,math.min(#scoretbl,10) do
print(i, scoretbl[i].name, scoretbl[i].score)
end
end
ShowOnly10()
Related
I'm trying to figure out how to randomly select multiple entries in a table.
This is what I have currently
local letters = {"w", "x", "y", "z"}
function randomletterselect()
local randomletters = {}
for i,v in pairs(letters) do
table.insert(randomletters,i)
end
local letter = letters[randomletters[math.random(#randomletters)]]
-- set multiple selected letters to the new table?
end
randomletterselect()
this code here works for selecting ONE random element(letter) from the table. essentially, when I run this, I want it to be multiple random letters selected. for example, one time it may select x,y another time it may be x,y,z.
The closest thing I found was honestly just what I had figured out, in this post Randomly select a key from a table in Lua
You can do...
randomletterselect=function()
local chars={}
for i=65,math.random(65,90) do
table.insert(chars,string.char(math.random(65,90)):lower())
end
print(table.concat(chars,','))
return chars
end
randomletterselect()
...for lowercase letters.
And this version returns a table without doubles...
randomletterselect=function()
local chars=setmetatable({},{__name='randomletters'})
for i=65,90 do
table.insert(chars,string.char(i):lower())
end
for i=1,math.random(#chars) do
table.remove(chars,math.random(#chars))
end
print(#chars,table.concat(chars,','))
return chars
end
local tbl = {'a', 'b', 'c', 'd'} -- your characters here
local MIN_NUM, MAX_NUM = 1, 2 ^ #tbl - 1
-- if the length of the table has changed, MAX_NUM gonna change too
math.randomseed(os.time())
local randomNum = math.random(MIN_NUM, MAX_NUM)
local function getRandomElements(num)
local rsl = {}
local cnt = 1
while num > 0 do
local sign = num % 2 -- to binary
-- if the num is 0b1010, sign will be 0101
num = (num - sign)/2
if sign == 1 then
local idx = #rsl + 1
-- use tbl[#tbl + 1] to expand the table (array)
rsl[idx] = tbl[cnt]
end
cnt = cnt + 1
end
return table.concat(rsl)
end
print(getRandomElements(randomNum))
I have another method to solve the problem, try.
MIN_NUM should be 1 cuz when its 0, getRandomElements will return an empty string
I'm creating a program for a turtle in ComputerCraft. The program is going to make the turtle control a warehouse of storage for my items in the game. It will check what item I put in, then it will figure out the chest's location, go there, and dump it in. I am storing the locations of each chest in a table. For example:
cobblestone = {2,0,1}
That tells the turtle that the cobblestone chest is stored at position x=2 y=0 and z=1. To get the turtle to tell what it needs to store, it does:
itemDetails = turtle.getItemDetail()
name = string.gsub(itemDetails.name, "minecraft:", "")
This gets the turtle to get the details of the item. It then sets a variable to be the name of the item minus the minecraft: at the beginning of it (I can't have a variable called "minecraft:cobblestone"). I don't know how to use this variable to call the table and find its position for the turtle to go to it. If anybody can help, I would appreciate any of the help. Thanks in advance!
Also, just a heads up, the code is still set up for debugging and testing purposes. The setup is a turtle, with an input chest in front of it, a fuel chest to the right, and the warehouse behind it.
I've tried doing:
cobblestone = {2,0,1}
--Putting a piece of cobblestone in--
itemDetails = turtle.getItemDetail()
--Returning name of "minecraft:cobblestone"--
name = string.gsub(itemDetails.name, "minecraft:", "")
print name[1]
So far this hasn't worked.
pos = {0,0,0}
looking = 0
cobblestone = {2,0,1}
function fuel()
if turtle.getFuelLevel() < 20 then
turtle.select(16)
turtle.refuel(1)
end
end
function left()
turtle.turnLeft()
looking = looking - 1
if looking < 0 then
looking = 3
end
print(looking)
end
function right()
turtle.turnRight()
looking = looking + 1
if looking > 3 then
looking = 0
end
print(looking)
end
function forward()
fuel()
if turtle.forward() then
if looking == 0 then
pos[1] = pos[1] - 1
elseif looking == 1 then
pos[3] = pos[3] - 1
elseif looking == 2 then
pos[1] = pos[1] + 1
elseif looking == 3 then
pos[3] = pos[3] + 1
else
print("wot")
end
end
end
function up()
fuel()
turtle.up()
pos[2] = pos[2] + 1
end
function down()
fuel()
turtle.down()
pos[2] = pos[2] - 1
end
function goHome()
while pos[3] > 0 do
while looking > 1 do
left()
end
forward()
end
while pos[2] > 0 do
down()
end
while pos[1] > 0 do
while looking > 0 do
left()
end
forward()
end
end
while true do
turtle.select(1)
while not turtle.suck() do
sleep(1)
end
itemDetails = turtle.getItemDetail()
name = string.gsub(itemDetails.name, "minecraft:", "")
print(name)
while looking < 2 or looking > 2 do
left()
end
for i = pos[1],name[1]-1 do
forward()
end
while looking > 3 or looking < 3 do
right()
end
for i = pos[3],name[3]-1 do
forward()
end
for i = pos[2],name[2]-1 do
up()
end
while looking < 2 or looking > 2 do
left()
end
turtle.select(1)
turtle.drop()
goHome()
end
I want to be able to do:
cobblestone = {2,0,1}
--Putting a piece of cobblestone in--
itemDetails = turtle.getItemDetail()
--Returning name of "minecraft:cobblestone"--
name = string.gsub(itemDetails.name, "minecraft:", "")
print name[1]
and have the turtle print the same thing as
cobblestone[1]
which would be 2. However, it returns with nil.
Currently, your cobblestone is global, what is bad for this example. At first, store all elements like this:
local myelems = {
cobblestone = {2,0,1};
grass = {3,1,2};
}
and so on. Use local variables when you can, it's good practice in programming at all.
So let's look at your code:
-- Returning name of "minecraft:cobblestone"
local name = string.gsub(itemDetails.name, "minecraft:", "")
print(name[1])
What it does? (I've changed it a bit)
At first,string.gsub look like an overkill here, use string.match instead:
local name = itemDetails.name:match("^minecraft:(.+)$")
Here itemDetails.name:match is same as calling string.match with itemDetails.name as first argument. It can be used for all string functions.
So here name is string variable. Indexing strings in different languages may have different results. In lua in actually provide access to all string functions to make calls to them easier (as above). There is no such function as string[1], so you get nil. However, now we have table myelems in which keys are strings and values are your tables.
Full code:
-- Table for all elements
local myelems = {
cobblestone = {2,0,1};
grass = {3,1,2};
}
-- Putting a piece of cobblestone in
local itemDetails = turtle.getItemDetail()
--Returning name of "minecraft:cobblestone"
local name = itemDetails.name:match("^minecraft:(.+)$")
-- Get our table
local elem = myelems[name]
if elem then
print(elem[1], elem[2], elem[3])
end
--The view of the table
local originalStats = {
Info = {Visit = false, Name = "None", Characters = 1},
Stats = {Levels = 0, XP = 0, XP2 = 75, Silver = 95},
Inventory = {
Hats = {"NoobHat"},
Robes = {"NoobRobe"},
Boots = {"NoobBoot"},
Weapons = {"NoobSword"}
}
}
local tempData = {}
--The arrangement here
function Module:ReadAll(player)
for k,v in pairs(tempData[player]) do
if type(v) == 'table' then
for k2, v2 in pairs(v) do
print(k2) print(v2)
if type(v2) == 'table' then
for k3, v3 in pairs(v2) do
print(k3) print(v3)
end
else
print(k2) print(v2)
end
end
else
print(k) print(v)
end
end
end
I'm sorry, but I can't seem to figure out how to arrange this 'ReadAll' function to where It'll show all the correct stats in the right orders.
The output is something like this:
Boots
table: 1A73CF10
1
NoobBoot
Weapons
table: 1A7427F0
1
NoobSword
Robes
table: 1A743D50
1
NoobRobe
Hats
table: 1A73C9D0
1
NoobHat
XP2
75
XP2
75
Levels
2
Levels
2
XP
0
XP
0
Here's a way to print all the elements without double or table reference values showing up.
As the name states, this function will print all the elements within a table, no matter how many nested tables there are inside it. I don't have a way to order them at the moment, but I'll update my answer if I find a way. You can also get rid of the empty spaces in the print line, I just used it so it would look neater. Let me know if it works.
function allElementsInTable(table)
for k,v in pairs(table) do
if type(table[k]) == 'table' then
print(k .. ":")
allElementsInTable(v)
else
print(" " .. k .. " = " .. tostring(v))
end
end
end
--place the name of your table in the parameter for this function
allElementsInTable(originalStats)
After more experimenting, I got this, if anyone wants it, feel free to use it.
tempData = { Info = {Visit = false, Name = 'None'},
Stats = {LVL = 0, XP = 0, Silver = 75},
Inventory = { Armors = {'BasicArmor'},
Weapons = {'BasicSword'} }
}
function Read()
for i, v in pairs(tempData['Info']) do
print(i..'\t',v)
end
----------
for i2, v2 in pairs(tempData['Stats']) do
print(i2..'\t',v2)
end
----------
for i3, v3 in pairs(tempData['Inventory']) do
print(i3..':')
for i4, v4 in pairs(v3) do
print('\t',v4)
end
end
end
Read()
Don't expect table's fields to be iterated with pairs() in some specific order. Internally Lua tables are hashtables, and the order of fields in it is not specified at all. It will change between runs, you can't have them iterated in the same order as they were filled.Only arrays with consecutive integer indices will maintain the order of their elements.
I want to create a very simple object oriented program. How can I list object fields (e.g., all customer names)? What is wrong with the following code? for k, v in ipairs() didn't work.
do
local Account = {}
function Account:Current()
return self.B
end
function Account:Deposit(D)
self.B = self.B + D
end
function Account:Withdraw(W)
self.B = self.B - W
end
function BankAccount(Id, Name, N)
return {B=N,Current=Account.Current,Deposit=Account.Deposit,Withdraw=Account.Withdraw,AccountName=Name,AccountId=Id}
end
end
local Id = 1
local CustomerDatabase = {}
while true do
print("Select an option or press q to quit")
print("1. Create new customer entry")
print("5. List current customer database")
local Option = io.read("*line")
if Option == "q" then break
elseif Option == "1" then
print("Enter the name")
local Name = io.read("*line")
print("Enter initial amount")
local InitialAmount = io.read("*line")
BankAccount(Id, Name, InitialAmount)
table.insert(CustomerDatabase, BankAccount)
Id = Id + 1
elseif Option == "5" then
for k, v in ipairs(CustomerDatabase) do
print(k .. v.AccountName)
end
end
end
BankAccount(Id, Name, InitialAmount)
table.insert(CustomerDatabase, BankAccount)
Here, BankAccount is a function, you are inserting into the table a function. That's why v.AccountName is invalid, functions can't be indexed.
What you should do is to add the account object:
local account = BankAccount(Id, Name, InitialAmount)
table.insert(CustomerDatabase, account)
I need a piece of code in lua language that can find sequential items in an array that the number of item in the group exceeds a specific nubmer. Example:if I have the array(the numbers won't be in the right order, randomly distributed)->( 2,5,9,10,11,21,23,15,14,12,22,13,24 ) ; there are two sequential groups (9,10,11,12,13,14,15) and (21,22,23,24 ) . I want the first group to be found if the specific number say (4) or more, or I can get the two groups if the number is (3) or less for example.
thanks
The logical way would seem to be to reorder the table and look for gaps in the sequences.
function table.copy(t)
local t2 = {}
for k,v in pairs(t) do
t2[k] = v
end
return t2
end
function groups(org, cnt)
-- Returns a table containing tables containing the groups found
local res = {}
local group = {}
tbl = table.copy(org) -- Prevent reordering of Original Table
table.sort(tbl)
local last = nil
for _,val in ipairs(tbl) do
if last and last + 1 ~= val then
if #group >= cnt then
table.insert(res,group)
end
group = {}
end
table.insert(group,val)
last = val
end
if #group >= cnt then
table.insert(res,group)
end
return res
end
local org = { 2,5,9,10,11,21,23,15,14,12,22,13,24 }
local result = groups(org,3)
print('Number of Groups',#result)