Use a string of expressions in a method for python - parsing

For example, if I have the string:
"id=100 id2=200 id3=300 ..."
where the variable names, values, and number of expressions can be anything.
How can I then use that string in a method that is used like this:
method(id=100,id2=200,id3=300,...)
I get the string from a command line argument.

We parse them iteratively:
pairs = "id=100 id2=200 id3=300".split(' ')
res = {}
for p in pairs:
k,v = p.rsplit('=', 1)
res[k] = v
print res # prints {'id2': '200', 'id': '100', 'id3': '300'}
# now we can send the dictionary to the method

You can first convert it to a dictionary:
>>> s = "id=100 id2=200 id3=300"
>>> d = dict(a.split('=') for a in s.plit())
>>> print d
{'id2': '200', 'id': '100', 'id3': '300'}
And now use it in functions:
>>> method(**d)

Related

How do I extract numbers from a string?

How would I extract every number from a string and put them in an array?
For example the string:
"\113\115\106\111\117\41\40\105\102\109\109\112\40\42"
You can use string.gmatch like this:
local my_array = {}
local my_string = "\\113\\115\\106\\111\\117\\41\\40\\105\\102\\109\\109\\112\\40\\42"
print(my_string) --note how the string is \ followed by digits
for number in string.gmatch(my_string, "\\(%d+)") do
my_array[#my_array + 1] = tonumber(number)
print(number)
end
This will get you an table with all the numbers from your string.
The \ is escaped in my example to make it equal to the string you stated.
If i misunderstood your question and the numbers you want are from the chars then you need to do
local my_array = {}
local my_string = "\113\115\106\111\117\41\40\105\102\109\109\112\40\42"
print(my_string) --note how the string is letters
for char in string.gmatch(my_string, ".") do
my_array[#my_array + 1] = string.byte(char)
print(char, my_array[#my_array])
end

Lua, Modify print function

I am writing a generic Log() function in lua which utilizes lua print function:
Log (variable, 'String: %s ', str, 'Word: %d', w)
Currently I'm using below approach:
print(string.format (variable, 'String: %s ', str, 'Word: %d', w))
I tried something like:
Log = function(...) begin
return print(string.format(...))
end
But it doesn't work, Is this correct approach? Or Is there any better more generic way to get this done?
If you just want to print a sequence of values, you can do that with print:
print(variable, 'String: %s ', str, 'Word: %d', w)
What you seem to want is something more complicated. Your algorithm seems to be:
For each argument:
If the argument is not a string, then convert it to a string and print it.
If the argument is a string, figure out how many % patterns it has (let us call this number k). Pass string.format the current argument string and the following k parameters, printing the resulting string. Advance k parameters.
That's a much more complicated algorithm than can be done in a one-line system.
Using Lua 5.3, here's what such a function would look like (note: barely tested code):
function Log(...)
local values = {}
local params = table.pack(...)
local curr_ix = 1
while (curr_ix <= params.n) do
local value = params[curr_ix]
if(type(value) == "string") then
--Count the number of `%` characters, *except* for
--sequential `%%`.
local num_formats = 0
for _ in value:gmatch("%%[^%%]") do
num_formats = num_formats + 1
end
value = string.format(table.unpack(params, curr_ix, num_formats + curr_ix))
curr_ix = curr_ix + num_formats
end
values[#values + 1] = value
curr_ix = curr_ix + 1
end
print(table.unpack(values))
end
I don't think your current approach works, because the first argument of string.format expects the format specifier, not the rest of the arguments.
Anyway, this is the way to combine formatting and printing together:
Log = function(...)
return print(string.format(...))
end
And call it like this:
Log("String: %s Number: %d", 'hello' , 42)
Also, it might be better to make the format specifier argument more explicit, and use io.write instead of print to get more control over printing:
function Log(fmt, ...)
return io.write(string.format(fmt, ...))
end

How to convert string into a table in Lua

I am having a table data in string form. Sample is given below:
{"engName1":"HOLDER","validDurPeriod":3,"engName2":"INFORMATION","appStatus":2,"stayExpDate":"01/10/2012","engName3":"","appExpDate":"12/04/2010"}
How can I convert it into a proper table type variable so that I can access keys.I am new to lua and I am not aware if there is any existing method to do so.
There is plenty of JSON parsers available for Lua, for example dkjson:
local json = require ("dkjson")
local str = [[
{
"numbers": [ 2, 3, -20.23e+2, -4 ],
"currency": "\u20AC"
}
]]
local obj, pos, err = json.decode (str, 1, nil)
if err then
print ("Error:", err)
else
print ("currency", obj.currency)
for i = 1,#obj.numbers do
print (i, obj.numbers[i])
end
end
Output:
currency €
1 2
2 3
3 -2023
4 -4
Try this code to start with
J=[[
{"engName1":"HOLDER","validDurPeriod":3,"engName2":"INFORMATION","appStatus":2,"stayExpDate":"01/10/2012","engName3":"","appExpDate":"12/04/2010"}
]]
J=J:gsub("}",",}")
L={}
for k,v in J:gmatch('"(.-)":(.-),') do
L[k]=v
print(k,v)
end
You'll still need to convert some values to number and remove quotes.
Alternatively, you can let Lua do the hard work, if you trust the source string. Just replace the loop by this:
J=J:gsub('(".-"):(.-),','[%1]=%2,\n')
L=loadstring("return "..J)()

LPeg Increment for Each Match

I'm making a serialization library for Lua, and I'm using LPeg to parse the string. I've got K/V pairs working (with the key explicitly named), but now I'm going to add auto-indexing.
It'll work like so:
#"value"
#"value2"
Will evaluate to
{
[1] = "value"
[2] = "value2"
}
I've already got the value matching working (strings, tables, numbers, and Booleans all work perfectly), so I don't need help with that; what I'm looking for is the indexing. For each match of #[value pattern], it should capture the number of #[value pattern]'s found - in other words, I can match a sequence of values ("#"value1" #"value2") but I don't know how to assign them indexes according to the number of matches. If that's not clear enough, just comment and I'll attempt to explain it better.
Here's something of what my current pattern looks like (using compressed notation):
local process = {} -- Process a captured value
process.number = tonumber
process.string = function(s) return s:sub(2, -2) end -- Strip of opening and closing tags
process.boolean = function(s) if s == "true" then return true else return false end
number = [decimal number, scientific notation] / process.number
string = [double or single quoted string, supports escaped quotation characters] / process.string
boolean = P("true") + "false" / process.boolean
table = [balanced brackets] / [parse the table]
type = number + string + boolean + table
at_notation = (P("#") * whitespace * type) / [creates a table that includes the key and value]
As you can see in the last line of code, I've got a function that does this:
k,v matched in the pattern
-- turns into --
{k, v}
-- which is then added into an "entry table" (I loop through it and add it into the return table)
Based on what you've described so far, you should be able to accomplish this using a simple capture and table capture.
Here's a simplified example I knocked up to illustrate:
lpeg = require 'lpeg'
l = lpeg.locale(lpeg)
whitesp = l.space ^ 0
bool_val = (l.P "true" + "false") / function (s) return s == "true" end
num_val = l.digit ^ 1 / tonumber
string_val = '"' * l.C(l.alnum ^ 1) * '"'
val = bool_val + num_val + string_val
at_notation = l.Ct( (l.P "#" * whitesp * val * whitesp) ^ 0 )
local testdata = [[
#"value1"
#42
# "value2"
#true
]]
local res = l.match(at_notation, testdata)
The match returns a table containing the contents:
{
[1] = "value1",
[2] = 42,
[3] = "value2",
[4] = true
}

Adding List Elements to a Dictionary

I am trying to take a list of words that I have imported from a textfile and make a dictionary , where the value is incremented each time the word is passed over in the loop. However, with the current code I have, none are added and only the value I add initiall is there when I print the dictionary. What am I doing wrong?
import pymysql
from os import path
import re
db = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='db_cc')
cursor = db.cursor()
cursor.execute("SELECT id, needsprocessing, SchoolID, ClassID, TaskID FROM sharedata WHERE needsprocessing = 1")
r = cursor.fetchall()
print(r)
from os import path
import re
noentities = len(r)
a = r[0][1]
b = r[0][2]
c = r[0][3]
d = r[0][4]
filepath = "/codecompare/%s/%s/%s/%s.txt" %(a, b, c, d)
print(filepath)
foo = open(filepath, "r")
steve = foo.read()
rawimport = steve.split(' ')
dictionary = {"for":0}
foo.close()
for word in rawimport:
if word in dictionary:
dictionary[word] +=1
else:
dictionary[word] = 1
print dictionary
Some rawimport values are as follows:
print rawimport
['Someting', 'something', 'dangerzones', 'omething', 'ghg', 'sdf', 'hgiinsfg', '932wrtioarsjg', 'fghbyghgyug', 'sadiiilglj']
Additionally, when trying to print from the code, it throws
... print dictionary
File "<stdin>", line 3
print dictionary
^
SyntaxError: invalid syntax
However, if I run print dictionary by itself it prints:
{'for': 0}
Which is evidence that for loop did nothing.
Any ideas?
Running Python 2.7.2
edit: updated to reflect closing of file and to make loop simpler
edit: added sample rawimport data
I received the same Traceback when working through this in the Python interpreter -- it arose from not leaving the context of the for loop:
>>> for word in rawimport:
... if word in dictionary:
... dictionary[word]+=1
... else:
... dictionary[word]=1
... print dictionary
File "<stdin>", line 6
print dictionary
^
The interpreter thinks your print statement belongs to the for loop, and errors because it's not appropriately indented. (If you did indent it, of course, it would print the dictionary during each pass). The solution to that (assuming you're doing this in the interpreter, which was how I reproduced your error) is hitting enter again:
>>> for word in rawimport:
... if word in dictionary:
... dictionary[word]+=1
... else:
... dictionary[word]=1
...
>>> print dictionary
{'for': 1, 'fghbyghgyug': 1, '932wrtioarsjg': 1, 'dangerzones': 1, 'sdf': 1, 'ghg': 1, 'Someting': 1, 'something': 1, 'omething': 1, 'sadiiilglj': 1, 'hgiinsfg': 1}
'''

Resources