In this code:
t = {
num = '',
}
t[0].num = '0'
t[1].num = '1'
t[2].num = '2'
Is there a way for me to delete t[0], then shift all of the table's values down, so that afterword it looks like this:
t[0].num = '1'
t[1].num = '2'
Example with imaginary functions:
t = {
num = '',
}
t[0].num = '0'
t[1].num = '1'
t[2].num = '2'
for i=0,tableLength(t) do
print(t[i])
end
--Output: 012
remove(t[0])
for i=0,tableLength(t) do
print(t[i])
end
--Output: 12
t = {
num = '',
}
t[0].num = '0'
t[1].num = '1'
t[2].num = '2'
This code will cause errors for indexing t[0], a nil value.
t only has one field and that is t.num
You need to do something like this:
t = {}
for i = 0, 2 do
t[i] = {num = tostring(i)}
end
if you want to create the desired demo table.
As there are many useful functions in Lua that assume 1-based indexing you I'd recommend starting at index 1.
local t = {1,2,3,4,5}
Option 1:
table.remove(t, 1)
Option 2:
t = {table.unpack(t, 2, #t)}
Option 3:
t = table.move(t, 2, #t, 1, t)
t[#t] = nil
Option 4:
for i = 1, #t-1 do
t[i] = t[i+1]
end
t[#t] = nil
There are more options. I won't list them all. Some do it in place, some result in new table objects.
As stated in this answer, by creating a new table using the result of table.unpack:
t = {table.unpack(t, 1, #t)}
I have a file with a large table. Need to open it, get certain values and replace other values with the new ones. With this example, Females and Males Classroom a and b must equal Teachers Classroom a and b.
Read as much as I can on IO, but I cannot seem to get this to work correctly. Any help will be greatly appreciated.
--file with sample data to test, original file has 7000+lines
theData =
{
["theSchool"] =
{
["theTeachers"] =
{
["theClassroom"] =
{
["a"] = 001,
["b"] = 002,
},
},
["theFemales"] =
{
["theClassroom"] =
{
["a"] = 005,
["b"] = 010,
},
},
["theMales"] =
{
["theClassroom"] =
{
["a"] = 012,
["b"] = 014,
},
},
},
}
Then the function file looks like this
local file = io.open(filepath,'r')
local newCa = '["a"] = '..theData.theSchool.theTeachers.theClassroom.a
local newCb = '["b"] = '..theData.theSchool.theTeachers.theClassroom.b
local replaceFa = '["a"] = '..tostring(theData.theSchool.theFemales.theClassroom.a)
local replaceFb = '["b"] = '..tostring(theData.theSchool.theFemales.theClassroom.b)
local replaceMa = '["a"] = '..tostring(theData.theSchool.theMales.theClassroom.a)
local replaceMb = '["b"] = '..tostring(theData.theSchool.theMales.theClassroom.b)
file:close()
--Will it work?
print("Original Values:")
print(newCa)
print(newCb)
print(replaceFa)
print(replaceFb)
print(replaceMa)
print(replaceMb)
file = io.open(filepath,'r+')
function lines_from(filepath)
lines = {}
for line in io.lines(filepath) do
lines[#lines + 1] = line
end
return lines
end
local lines = lines_from(filepath)
for k,v in ipairs(lines) do
if v == replaceFa then
file:write(newCa..'\n')
elseif v == replaceFb then
file:write(newCb..'\n')
elseif v == replaceMa then
file:write(newCa..'\n')
elseif v == replaceMb then
file:write(newCb..'\n')
else
file:write(v..'\n')
end
--('[' .. k .. ']', v)
end
--replaceF = {[a] = newCa, [b] = newCb}
--replaceM = {[a] = newCa, [b] = newCb}
--file:write(replaceF)
--file:write(replaceM)
--print(tostring(theData.theSchool.theFemales.theClassroom.a))
file:close()
file = io.open(filepath,'r')
--Did it work?
print("New Values:")
print(theData.theSchool.theTeachers.theClassroom.a)
print(theData.theSchool.theTeachers.theClassroom.b)
print(theData.theSchool.theFemales.theClassroom.a)
print(theData.theSchool.theFemales.theClassroom.b)
print(theData.theSchool.theMales.theClassroom.a)
print(theData.theSchool.theMales.theClassroom.b)```
> I'll remove all the print things after it works.
try this solution, loading the table in one read of the file will be faster, and writing is also better with one command write
--- read
local handle = io.open("data.lua",'rb')
local data = handle:read("*a")
handle:close()
data = data .. "\n return theData"
local t = loadstring(data)()
-- edit
theData.theSchool.theTeachers.theClassroom.a = theData.theSchool.theTeachers.theClassroom.a + 1
-- write
local function concat(t, r)
r = r or {}
for k,v in pairs(t) do
if type(v)=="table" then
r[#r+1] = string.format('\t["%s"]={\n',k )
concat(v, r)
r[#r+1] = "\t},\n"
else
r[#r+1] = string.format('\t\t["%s"]=%03s,\n',k ,v )
end
end
return r
end
local r = concat(t)
local text = "theData = { \n " .. table.concat(r) .. "}"
print(text) -- just control
local handle = io.open("data.lua",'wb')
local data = handle:write(text)
handle:close()
I started to learn lua (version 5.1) plus iup (version 3.5) library, but this issue shut me down :(
So, the clearest example from iup tutorial http://webserver2.tecgraf.puc-rio.br/iup/en/tutorial/tutorial3.html#Recent_Config
require("iuplua")
require("iupluaimglib")
--********************************** Utilities *****************************************
function str_find(str, str_to_find, casesensitive, start)
if (not casesensitive) then
return str_find(string.lower(str), string.lower(str_to_find), true, start)
end
return string.find(str, str_to_find, start, true)
end
function read_file(filename)
local ifile = io.open(filename, "r")
if (not ifile) then
iup.Message("Error", "Can't open file: " .. filename)
return nil
end
local str = ifile:read("*a")
if (not str) then
iup.Message("Error", "Fail when reading from file: " .. filename)
return nil
end
ifile:close()
return str
end
function write_file(filename, str)
local ifile = io.open(filename, "w")
if (not ifile) then
iup.Message("Error", "Can't open file: " .. filename)
return false
end
if (not ifile:write(str)) then
iup.Message("Error", "Fail when writing to file: " .. filename)
end
ifile:close()
return true
end
--********************************** Main (Part 1/2) *****************************************
-- it`s there:
config = iup.config{} ------ here it is, first error
config.app_name = "simple_notepad"
config:Load()
lbl_statusbar = iup.label{title = "Lin 1, Col 1", expand = "HORIZONTAL", padding = "10x5"}
multitext = iup.text{
multiline = "YES",
expand = "YES"
}
font = config:GetVariable("MainWindow", "Font")
if (font) then
multitext.font = font
end
item_open = iup.item{title = "&Open...\tCtrl+O"}
item_saveas = iup.item{title="Save &As...\tCtrl+S"}
item_font = iup.item{title="&Font..."}
item_about = iup.item{title="&About..."}
item_find = iup.item{title="&Find...\tCtrl+F"}
item_goto = iup.item{title="&Go To..."}
item_exit = iup.item{title="E&xit"}
--********************************** Callbacks *****************************************
function config:recent_cb()
local filename = self.title
local str = read_file(filename)
if (str) then
multitext.value = str
end
end
function multitext:caret_cb(lin, col)
lbl_statusbar.title = "Lin "..lin..", Col "..col
end
function item_open:action()
local filedlg = iup.filedlg{
dialogtype = "OPEN",
filter = "*.txt",
filterinfo = "Text Files",
parentdialog=iup.GetDialog(self)
}
filedlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(filedlg.status) ~= -1) then
local filename = filedlg.value
local str = read_file(filename)
if (str) then
config:RecentUpdate(filename)
multitext.value = str
end
end
filedlg:destroy()
end
function item_saveas:action()
local filedlg = iup.filedlg{
dialogtype = "SAVE",
filter = "*.txt",
filterinfo = "Text Files",
parentdialog=iup.GetDialog(self)
}
filedlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(filedlg.status) ~= -1) then
local filename = filedlg.value
if (write_file(filename, multitext.value)) then
config:RecentUpdate(filename)
end
end
filedlg:destroy()
end
function item_exit:action()
config:DialogClosed(iup.GetDialog(self), "MainWindow")
config:Save()
config:destroy()
return iup.CLOSE
end
function item_goto:action()
local line_count = multitext.linecount
local lbl_goto = iup.label{title = "Line Number [1-"..line_count.."]:"}
local txt_goto = iup.text{mask = iup.MASK_UINT, visiblecolumns = 20} --unsigned integer numbers only
local bt_goto_ok = iup.button{title = "OK", text_linecount = 0, padding = "10x2"}
bt_goto_ok.text_linecount = line_count
function bt_goto_ok:action()
local line_count = tonumber(self.text_linecount)
local line = tonumber(txt_goto.value)
if (line < 1 or line >= line_count) then
iup.Message("Error", "Invalid line number.")
return
end
goto_dlg.status = 1
return iup.CLOSE
end
local bt_goto_cancel = iup.button{title = "Cancel", padding = "10x2"}
function bt_goto_cancel:action()
goto_dlg.status = 0
return iup.CLOSE
end
local box = iup.vbox{
lbl_goto,
txt_goto,
iup.hbox{
iup.fill{},
bt_goto_ok,
bt_goto_cancel,
normalizesize="HORIZONTAL",
},
margin = "10x10",
gap = "5",
}
goto_dlg = iup.dialog{
box,
title = "Go To Line",
dialogframe = "Yes",
defaultenter = bt_goto_ok,
defaultesc = bt_goto_cancel,
parentdialog = iup.GetDialog(self)
}
goto_dlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(goto_dlg.status) == 1) then
local line = txt_goto.value
local pos = iup.TextConvertLinColToPos(multitext, line, 0)
multitext.caretpos = pos
multitext.scrolltopos = pos
end
goto_dlg:destroy()
end
function item_find:action()
local find_dlg = self.find_dialog
if (not find_dlg) then
local find_txt = iup.text{visiblecolumns = "20"}
local find_case = iup.toggle{title = "Case Sensitive"}
local bt_find_next = iup.button{title = "Find Next", padding = "10x2"}
local bt_find_close = iup.button{title = "Close", padding = "10x2"}
function bt_find_next:action()
local find_pos = tonumber(find_dlg.find_pos)
local str_to_find = find_txt.value
local casesensitive = (find_case.value == "ON")
-- test again, because it can be called from the hot key
if (not str_to_find or str_to_find:len()==0) then
return
end
if (not find_pos) then
find_pos = 1
end
local str = multitext.value
local pos, end_pos = str_find(str, str_to_find, casesensitive, find_pos)
if (not pos) then
pos, end_pos = str_find(str, str_to_find, casesensitive, 1) -- try again from the start
end
if (pos) and (pos > 0) then
pos = pos - 1
find_dlg.find_pos = end_pos
iup.SetFocus(multitext)
multitext.selectionpos = pos..":"..end_pos
local lin, col = iup.TextConvertPosToLinCol(multitext, pos)
local pos = iup.TextConvertLinColToPos(multitext, lin, 0) -- position at col=0, just scroll lines
multitext.scrolltopos = pos
else
find_dlg.find_pos = nil
iup.Message("Warning", "Text not found.")
end
end
function bt_find_close:action()
iup.Hide(iup.GetDialog(self)) -- do not destroy, just hide
end
box = iup.vbox{
iup.label{title = "Find What:"},
find_txt,
find_case,
iup.hbox{
iup.fill{},
bt_find_next,
bt_find_close,
normalizesize="HORIZONTAL",
},
margin = "10x10",
gap = "5",
}
find_dlg = iup.dialog{
box,
title = "Find",
dialogframe = "Yes",
defaultenter = bt_next,
defaultesc = bt_close,
parentdialog = iup.GetDialog(self)
}
-- Save the dialog to reuse it
self.find_dialog = find_dlg -- from the main dialog */
end
-- centerparent first time, next time reuse the last position
find_dlg:showxy(iup.CURRENT, iup.CURRENT)
end
function item_font:action()
local font = multitext.font
local fontdlg = iup.fontdlg{value = font, parentdialog=iup.GetDialog(self)}
fontdlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(fontdlg.status) == 1) then
multitext.font = fontdlg.value
config:SetVariable("MainWindow", "Font", fontdlg.value)
end
fontdlg:destroy()
end
function item_about:action()
iup.Message("About", " Simple Notepad\n\nAutors:\n Gustavo Lyrio\n Antonio Scuri")
end
--********************************** Main (Part 2/2) *****************************************
recent_menu = iup.menu{}
file_menu = iup.menu{
item_open,
item_saveas,
iup.separator{},
iup.submenu{title="Recent &Files", recent_menu},
item_exit
}
edit_menu = iup.menu{item_find, item_goto}
format_menu = iup.menu{item_font}
help_menu = iup.menu{item_about}
sub_menu_file = iup.submenu{file_menu, title = "&File"}
sub_menu_edit = iup.submenu{edit_menu, title = "&Edit"}
sub_menu_format = iup.submenu{format_menu, title = "F&ormat"}
sub_menu_help = iup.submenu{help_menu, title = "&Help"}
menu = iup.menu{
sub_menu_file,
sub_menu_edit,
sub_menu_format,
sub_menu_help,
}
btn_open = iup.button{image = "IUP_FileOpen", flat = "Yes", action = item_open.action, canfocus="No", tip = "Open (Ctrl+O)"}
btn_save = iup.button{image = "IUP_FileSave", flat = "Yes", action = item_saveas.action, canfocus="No", tip = "Save (Ctrl+S)"}
btn_find = iup.button{image = "IUP_EditFind", flat = "Yes", action = item_find.action, canfocus="No", tip = "Find (Ctrl+F)"}
toolbar_hb = iup.hbox{
btn_open,
btn_save,
iup.label{separator="VERTICAL"},
btn_find,
margin = "5x5",
gap = 2,
}
vbox = iup.vbox{
toolbar_hb,
multitext,
lbl_statusbar,
}
dlg = iup.dialog{
vbox,
title = "Simple Notepad",
size = "HALFxHALF",
menu = menu,
close_cb = item_exit.action,
}
function dlg:k_any(c)
if (c == iup.K_cO) then
item_open:action()
elseif (c == iup.K_cS) then
item_saveas:action()
elseif (c == iup.K_cF) then
item_find:action()
elseif (c == iup.K_cG) then
item_goto:action()
end
end
config:RecentInit(recent_menu, 10)
-- parent for pre-defined dialogs in closed functions (IupMessage)
iup.SetGlobal("PARENTDIALOG", iup.SetHandleName(dlg))
config:DialogShow(dlg, "MainWindow")
-- to be able to run this script inside another context
if (iup.MainLoopLevel()==0) then
iup.MainLoop()
iup.Close()
end
don`t working:
error output:
wlua: source.wlua:52: attempt to call field 'config' (a nil value)
So, why it isn`t working?
I want to use Bing search results for my webpage. To use their json data I found this solution:
new_bing_results = bing_results[0][:Web]
result = { }
result[:title] = new_bing_results[0][:Title]
result[:description] = new_bing_results[0][:Description]
result[:url] = new_bing_results[0][:Url]
result[:display_url] = new_bing_results[0][:DisplayUrl]
result[:title1] = new_bing_results [1][:Title]
result[:description1] = new_bing_results [1][:Description]
result[:url1] = new_bing_results [1][:Url]
result[:display_url1] = new_bing_results [1][:DisplayUrl]
result[:title2] = new_bing_results [2][:Title]
result[:description2] = new_bing_results [2][:Description]
result[:url2] = new_bing_results [2][:Url]
result[:display_url2] = new_bing_results [2][:DisplayUrl]
....
result
How can I create a loop that is doing the same thing 50 times without having to repeat the same code.
I tried this but only get errors:
new_bing_results = bing_results[0][:Web]
$i = 0
$num = 50
result2 = {}
while $i < $num do
result[:title$i] = new_bing_results[$i][:Title]
......
end
result
The problem is that I do not find a solution for adding my $i number to the key result[:title] as in the value new_bing_results[$i][:Title]
This should do the trick
result = {}
50.times do |i|
result["title#{i}".to_sym] = new_bing_results[i][:Title]
result["description#{i}".to_sym] = new_bing_results[i][:Description]
result["url#{i}".to_sym] = new_bing_results[i][:Url]
result["display_url#{i}".to_sym] = new_bing_results[i][:DisplayUrl]
end
50.times will run from 0 to 49 and you can use interpolation to avoid the repetition.
You can use .to_sym method. For example:
new_bing_results = [{Title: "Title"}]
result = {}
result["title#{i}".to_sym] = new_bing_results[i][:Title]
result
=> {:title0=>"Title"}
You can use string interpolation and then the to_sym method.
result = {}
50.times do |n|
result["title#{n}".to_sym] = new_bing_results[n][:Title]
end
I'm trying to have a form usable for both creating a new record or updating another. Currently it is doing it through the value of a textbox (new or edit). The structure works fine, but for some reason, when it is performing the edit function, it is saving changes to the wrong record. For instance, if I am editing record 1027, when i submit it, it'll update record 1073. Its consistent, it'll always update the same, wrong record. Edit 1000, it'll update 1073; if i update 1081, it'll update 1073, and so on. Is there a way to specify which record it should be editing? yes, the record number is the primary key/id. Heres the code:
Private Sub btnSubmit_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strTable As String
Dim strField As String
Dim ID As Long
Dim newID As Long
strTable = "record_holdData"
Set db = CurrentDb
Set rs = db.OpenRecordset(strTable)
'button has 2 modes
If txtMode.Value = "NEW" Then
With rs
.AddNew
.Fields("PO_no") = txtPONum
.Fields("prodSupervisor") = cboProdSup
.Fields("qaSupervisor") = cboQASup
.Fields("labTech") = cboLabTech
.Fields("flavor") = cboFlavor
.Fields("lineNumber") = cboLineNumber
.Fields("container") = cboContainer
.Fields("package") = cboPackage
.Fields("holdQty") = txtQty
.Fields("productionDate") = txtProdDate
.Fields("dateCode") = txtDatecode
.Fields("component") = cboComponent
.Fields("nonconformance") = cboDiscrepancy
.Fields("foundDuring") = cboFoundAt
.Fields("responsibility") = cboRespCode
.Fields("comments") = txtDescription
.Fields("rootCause") = txtRootCause
.Fields("holdStatus") = 1
.Fields("dateOpened") = Now()
.Update
.Bookmark = .LastModified
newID = !ID
End With
MsgBox ("Hold information saved!")
btnPrintTag.Enabled = True
DoCmd.OpenReport "Holdtag", acViewPreview, , "[ID] = " & newID
DoCmd.Close
ElseIf txtMode.Value = "EDIT" Then
'do editing stuff
With rs
.Edit
.Fields("PO_no") = txtPONum
.Fields("prodSupervisor") = cboProdSup
.Fields("qaSupervisor") = cboQASup
.Fields("labTech") = cboLabTech
.Fields("flavor") = cboFlavor
.Fields("lineNumber") = cboLineNumber
.Fields("container") = cboContainer
.Fields("package") = cboPackage
.Fields("holdQty") = txtQty
.Fields("productionDate") = txtProdDate
.Fields("dateCode") = txtDatecode
.Fields("component") = cboComponent
.Fields("nonconformance") = cboDiscrepancy
.Fields("foundDuring") = cboFoundAt
.Fields("responsibility") = cboRespCode
.Fields("comments") = txtDescription
.Fields("rootCause") = txtRootCause
.Fields("lastEditDate") = Now()
.Update
End With
MsgBox ("Information Updated")
End If
End Sub
Sorry i caught it. Problem was I was basically redefining the recordset each time the subroutine was called. I changed the second block to the following:
ElseIf txtMode.Value = "EDIT" Then
'do editing stuff
Set rs = db.OpenRecordset("SELECT * FROM record_holdData WHERE ID=" & txtID)
With rs
.Edit
.Fields("PO_no") = txtPONum
.Fields("prodSupervisor") = cboProdSup
.Fields("qaSupervisor") = cboQASup
.Fields("labTech") = cboLabTech
.Fields("flavor") = cboFlavor
.Fields("lineNumber") = cboLineNumber
.Fields("container") = cboContainer
.Fields("package") = cboPackage
.Fields("holdQty") = txtQty
.Fields("productionDate") = txtProdDate
.Fields("dateCode") = txtDatecode
.Fields("component") = cboComponent
.Fields("nonconformance") = cboDiscrepancy
.Fields("foundDuring") = cboFoundAt
.Fields("responsibility") = cboRespCode
.Fields("comments") = txtDescription
.Fields("rootCause") = txtRootCause
.Fields("lastEditDate") = Now()
.Update
End With