Lua string comparison failing - lua
I am trying to group entries in a csv file into different tables in Lua, based on the last attribute. But for some reason the string comparison doesn't work. The following is the code:
trainer = {}
tester = {}
valer = {}
for line in io.lines(mlist) do
local split = {}
for token in string.gmatch(line, '([^,]+)') do
table.insert(split, token)
if token == 'val' then
print('heelo')
end
end
if split[5] == "val" then
print('hello world')
end
if split[5] == 'test' then
table.insert(tester, split[1])
elseif split[5] == 'train' then
table.insert(trainer, split[1])
elseif (split[5] == 'val') then
print('hello')
table.insert(valer, split[1])
end
end
The file mlist contains the following entries (It actually has a lot of records, but I am putting a few for testing):
050810,02747177,02747177,a2e9d8324c1f62cd5ecea499ceee624d,train
051087,02747177,02747177,89aff0d006fc22ff9405d3391cbdb79b,train
051145,02747177,02747177,c6ef918f335bb21c5896bab37ddebe7,train
051416,02747177,02747177,ec1c1aa7003cf68d49e6f7df978f3373,train
051506,02747177,02747177,a8b39c32604173c1d2b12aa6a0f050b3,train
051654,02747177,02747177,e3484284e1f301077d9a3c398c7b4709,train
001174,02747177,02747177,bf4dd114b53bd8f0d67352166d8df9fd,val
003009,02747177,02747177,2f1aed8925147120c62ac18334863d36,val
003735,02747177,02747177,c3b31dc8c48265ecfffc97a61124b1a9,val
004213,02747177,02747177,3a982b20a1c8ebf487b2ae2815c9,val
005241,02747177,02747177,91a4d060d380409c2056b4bd5d870b47,val
008467,02747177,02747177,4d6b6d392ec6b5b4c69692992c7aeb,val
008652,02747177,02747177,3be3e86b2fad511048d5a1386787189,val
008659,02747177,02747177,1e1015a06e43c0a5a44b6af22454453b,val
010510,02747177,02747177,62f4ed6e1df63042cecaed25e0da0964,val
013730,02747177,02747177,7069760a16db98f46c9e5b09a1c294d9,val
016657,02747177,02747177,ae3257e7e0dca9a4fc8569054682bff9,val
018178,02747177,02747177,86194a4645da1f19e14ca01ae177e9d,val
019142,02747177,02747177,e5b7b5112e396a49b581cc9c4410f841,val
021424,02747177,02747177,4088f2056763a95752e986a5f722a6f,val
022098,02747177,02747177,b77e94ab409def2b72745b90f9692729,val
022185,02747177,02747177,b51812771e42354f9996a93ae0c9395c,val
027358,02747177,02747177,5092afb4be0a2f89950ab3eaa7fe7772,val
028916,02747177,02747177,63adebf24a1de9ecf91cc5a18046145f,val
031579,02747177,02747177,1c3cf618a6790f1021c6005997c63924,val
032507,02747177,02747177,dc7ce614dc719649b394cfa64dfabe8e,val
034010,02747177,02747177,6a1b359efc20cd1aaec6ee5ba573fa6d,val
035290,02747177,02747177,c904d927672acd48ad8a0ee9b106700e,val
036604,02747177,02747177,f116f3c432856fccddd8899c86e55073,val
039697,02747177,02747177,c21d8f5641be31a285cac25b72167160,val
040234,02747177,02747177,330cdd681a0890b190fdbeabcd02777c,val
041653,02747177,02747177,b838c5bc5241a44bf2f2371022475a36,val
044825,02747177,02747177,af6fa396b2869446d4d8765e3910f617,val
046115,02747177,02747177,1cb574d3f22f63ebd493bfe20f94b6ab,val
046248,02747177,02747177,942887c8d668501681faebbdea6bd9be,val
046853,02747177,02747177,92fa62263ad30506d2b12aa6a0f050b3,val
046957,02747177,02747177,c77e8499be0ce1e04f3443b22038d340,val
048064,02747177,02747177,c18e807ff9858a51fb016d9401ff3e29,val
048971,02747177,02747177,18dbebd6527cffa254685f5f473de41f,val
051563,02747177,02747177,7c90fba6cd7f73871c1ef519b9196b63,val
I checked the type of split[5] and it is indeed string. I even tried
print(split[5] == 'val')
which prints false.
Thanks for the help!
There is a simpler (more generic) way of splitting your lines into buckets according to the last 'key', without using a series of if blocks to catch every possible 'key'. Something like this (use input redirection to load the file in this example):
local groups = {}
for line in io.lines() do
v,k = line:match '^(%d+),%d+,%d+,%x+,(%w+)$'
if v ~= nil and k ~= nil then -- or, just if k
local t = groups[k]
if t == nil then t = { v } else t[#t+1] = v end
groups[k] = t
end
end
-- And, to see table contents for verification...
for k,v in pairs(groups) do
print(k)
for i,v in ipairs(v) do print('',i,v) end
end
UPDATE/SOLUTION:
Thanks to the solution of Egor Skriptunoff in the comments, this has been solved. The problem is on Linux the CR and LF are interpreted differently, and I was indeed using a file made on Windows on Linux. So just ignoring the last character in every line solves it. According to Egor's solution modifying the inner for that is splitting with this works:
for token in line:gsub('\r', ''):gmatch('[^,]+') do
....
end
Thanks again to Egor for the solution and the explanation!
Related
Does such an encryption/cipher method exist?
while thinking of an idea to create an encryption/cipher method, I thought of one that I wondered existed already. The method I imagined was to have pre-set characters, but instead, randomly generate meanings for these characters. Here's what I mean: (Representation in Lua) local Keys = {'a','b','c',} -- Rest of table removed for simplicity for i,v in pairs(Keys) do Keys[v] = '' repeat if Key[v] then Keys[v] = Keys .. string.char(math.random(1,255)) else Keys[v] = string.char(math.random(1,255)) end until string.len(Keys[v]) == 4 end print(Keys) --> {'a' = "ą�vź",..} Then when you make a string and transcribe it with the Keys table, it'll come out as the meaning given to it. Pretty simple, could probably do more with it, but does something like this already exist (have an official name for the method, perhaps?)
Passwordless obfuscating is also done with ROT. Just for fun i do this... -- rot.lua -- Usage: Creates a table (i.e. rot) for using it with string.gsub('Hello World','(.)',rot) -- A '.' in gsub() is neccessary to hit every single char in a string -- ROT13 for chars, ROT5 for numbers, ROT8/ROT3/ROT2/ROT1 for signs -- IMPORTANT: Both key/value pairs has to be datatype string local args={...} local rotator=function(...) local args, rot, c ={...}, {}, '' -- ROT5 for numbers for i=48,52 do rot[c.char(i)]=c.char(i+5) end for i=53,57 do rot[c.char(i)]=c.char(i-5) end -- ROT13 for chars (upper and lower case) -- Uppercase letters (ROT13) for i=65,77 do rot[c.char(i)]=c.char(i+13) end for i=78,90 do rot[c.char(i)]=c.char(i-13) end -- Lowercase letters (ROT13) for i=97,109 do rot[c.char(i)]=c.char(i+13) end for i=110,122 do rot[c.char(i)]=c.char(i-13) end -- Signs (ROT8) for i=32,39 do rot[c.char(i)]=c.char(i+8) end for i=40,47 do rot[c.char(i)]=c.char(i-8) end -- Signs (ROT3) for i=58,60 do rot[c.char(i)]=c.char(i+3) end for i=61,63 do rot[c.char(i)]=c.char(i-3) end -- Signs (ROT2) for i=91,92 do rot[c.char(i)]=c.char(i+2) end for i=93,94 do rot[c.char(i)]=c.char(i-2) end -- Sign # and tabstop (ROT1) rot['\t']='#' rot['#']='\t' return args[1]:gsub('.',rot),rot end local _,rot=rotator('koyaanisqatsi') -- Extracting the rot table from function rotator if #args==2 and args[2]==':preload:' then table.insert(rot,rotator) return rot else return rotator end -- Conditional return when required and package.preload is triggered If required und furthermore in string table as: string.rot you can obfuscating and deobfuscating with the same function... > myvar='koyaanisqatsi' > print(myvar) koyaanisqatsi > myvar=myvar:rot() > print(myvar) xblnnavfdngfv > myvar=myvar:rot() > print(myvar) koyaanisqatsi
join two string to one table in Lua
I have 2 strings: fields="a,b,c,d,e" values="1,2,,4,5" I need a table, to get the pairs values like: print(result.a) -> "1" print(result.c) -> "" (or nil) Is it possible?
Here is an opportunity to exploit generators without a for loop. The code below runs two gmatch generators in tandem. fields="a,b,c,d,e" values="1,2,,4,5" fields=fields.."," ; F=fields:gmatch("(.-),") values=values.."," ; V=values:gmatch("(.-),") result={} while true do local k,v=F(),V() if k==nil or v==nil then break end result[k]=v end for k,v in pairs(result) do print(k,v) end
How to create a table of unique strings in Lua?
I'm trying to create a function that adds unique string to a table. I also wonder how to print the result. My Code : local t = {} function addUniqueString(str) --what should be here? end function printElements() --what should be here? end addUniqueString("apple") addUniqueString("orange") addUniqueString("banana") addUniqueString("apple") printElements() The Result I want : (order doesn't matter) apple orange banana
Since the order doesn't matter, you can just add strings as keys to the table: local t = {} function addUniqueString(str) t[str] = true end And to list the strings: function printElements() for k in pairs(t) do print(k) end end
How to get the following result by truncating data?
I have Coffeescript file in the following format. I have to generate all the possible combinations using the : :. I have already written the code for combinations. It is working fine. But, somehow the configuration file is changed & I have to modify that code. So, could anyone please help me to solve this problem? abTests: productRanking: version: 4 groups: [ ratio: default: 1 us: 0.90 me: 0.0 value: "LessPopularityEPC" , ratio: default: 0 us: 0.1 value: "CtrEpcJob" , ratio: default: 0 me: 1.0 value: "RandomPerVisitor" ] I would like to have the data formatted in the following format: productRanking: "LessPopularityEPC" "CtrEpcJob" "RandomPerVisitor" ] I am using the following code here : START_REGEXP = /# AB Tests/ END_REGEXP = /# Routes/ COMMENT_EXP = /#/ COMMA_REGEXP = /,/ START_BLOCK = /\[/ END_BLOCK = /]/ def Automate_AB_tests.abTestParser(input_file,output_file) raise "Source File doesn't exist at provided path" unless File.exists?(input_file) flag = false #setting default value of flag=FALSE to parse the data between two REGEX File.open(output_file, "w") do |ofile| #opening destination file in WRITE mode File.foreach(input_file) do |iline| #Reading each lines of source file flag = true if iline =~ START_REGEXP ofile.puts(iline.sub(" ", '').sub("value:",'')) if flag && (iline =~ /value/ || iline=~ /,/ || iline =~ /]/) unless (iline =~ COMMENT_EXP or iline =~ COMMA_REGEXP) flag = false if iline =~ END_REGEXP end end end
Assuming that what you want is to take each key under abTests, e.g. ProductRanking, and return a hash with those keys having the value of the value key in their first group, then like so: data['abTests'].each_with_object({}) do |(key, testData), resultingHash| resultingHash[key] = testData['groups'].first['value'] end However, if that's not what you want, then you need to be a bit more clear. Try working through the operations you want to achieve on paper, and break down your thought process step-by-step. The two operations that tend to be most useful when processing list or hash data are map and reduce (each_with_object being a form of reduction). Look through the documentation of the Enumerable module of Ruby for more info.
Assume that you have a ruby hash, which can be rewrite as data = {:abTests=>{:productRanking=>{:version=>4, :groups=>[{:ratio=>{:default=>1, :us=>0.9, :me=>0.0}, :value=>"LessPopularityEPC"}]}}} you can loop over this data hash to get your desired result for eg: result_hash = {} data[:abTests].each do |key, value| result_hash = {k.to_sym => value[:groups][0][:value]} puts result_hash end puts result_hash[:productRanking] //outputs "LessPopularityEPC"
calling config param from another function (concatenate global error)
local otherteam = {} function onLoad() ... Config.aaRange.enemyrange:addParam("enemy0", otherteam[0], SCRIPT_PARAM_ONOFF, false) Config.aaRange.enemyrange:addParam("enemy1", otherteam[1], SCRIPT_PARAM_ONOFF, false) Config.aaRange.enemyrange:addParam("enemy2", otherteam[2], SCRIPT_PARAM_ONOFF, false) end function onDraw() ... for k = 0, 3, 1 then if hero.charName == otherteam[k] then if (Config.aaRange.enemyrange."enemy" .. k) then ... end end end end I get Attempt to concatenate global enemy error while running this. I can easily fix this by just removing the for k loop and having seperate if statements with if (Config.aaRange.enemyrange.enemy0) then end if (Config.aaRange.enemyrange.enemy0) then end if (Config.aaRange.enemyrange.enemy0) then end But that just seems messy (I got more than 3 configs). I even tried: j = "enemy" .. k and adding j instead of enemy0 in the if statement but nothing. I'm guessing this is because I'm trying to add the string with a number? Sorry, only started using lua a few hours ago :x
Lua supports coercion, so adding a string to a number is valid. But if you write j = "enemy" .. k The interpreter takes Config.aaRange.enemyrange.j as Config.aaRange.enemyrange["j"], you should use Config.aaRange.enemyrange[j] instead. Without another variable, you can write if Config.aaRange.enemyrange["enemy" .. k] then Or better: if Config.aaRange.enemyrange["enemy" .. tostring(k)] then