I have some inherited legacy language code snippets stored in a database table that I need to transform to a SQL like syntax so it can be used more effectively.
For example, one of the snippets is of the form
keyword = [a,b,c,x:y,d,e,f,p:q]
to indicate either discrete comma separate values or a range of colon-delimited values
How can I transform this to the equivalent SQL friendly snippet which would be
keyword in (a,b,c) or keyword between x and y or keyword in (d,e,f) or keyword between p and q
Thanks
It isn't regex but the first this that comes to mind it extracting the text within the square brackets so you have
textVariable = a,b,c,x:y,d,e,f,p:q
then split with the columns so you have an array where each element is part of the string. So your resulting array would be
array[0] = a
...
array[3] = x:y
...
Then go through your array and create the final string you want. something like this (though it isn't tested)
finalString = ""
tempString = ""
for (int i = 0, i < array.length; i++) {
if (array[i].contains(":")) { // then it needs to be between the two values
if (finalString.length > 0) {
finalString = finalString + " or "; // need to add an 'or'
}
if (tempString.length > 0) { // then need to add the keyword in (...) to finalString
finalString = finalString + tempString + ") or ";
}
temparray = array[i].split(":")
finalString = finalString + " keyword between " + temparray[0] + " and " + temparray[1]
} else {
if (tempString.length = 0) {
tempString= "keyword in ("; // need to start the next set
} else {
tempString = tempString + ", "
}
tempString = tempString + array[i];
}
}
Related
I have a question I wrote this script to format an arabic text to a certain format. But I found a problem then when I type a longer sentence it adds more dots then there are letters. I will paste the code here and explain what the problem is.
import itertools
while True:
input_cloze_deletion = input("\nEnter: text pr 'exit'\n> ")
input_exit_check = input_cloze_deletion.strip().lower()
if input_exit_check == "exit":
break
# copy paste
interpunction_list = ["الله", ",", ".", ":", "?", "!", "'"]
# copy paste
interpunction_list = [ ",", ".", ":", "?", "!", "'", "-", "(", ")", "/", "الله", "اللّٰـه"]
text_replace_0 = input_cloze_deletion.replace(",", " ,")
text_replace_1 = text_replace_0.replace(".", " .")
text_replace_2 = text_replace_1.replace(":", " :")
text_replace_3 = text_replace_2.replace(";", " ;")
text_replace_4 = text_replace_3.replace("?", " ?")
text_replace_5 = text_replace_4.replace("!", " !")
text_replace_6 = text_replace_5.replace("'", " ' ")
text_replace_7 = text_replace_6.replace("-", " - ")
text_replace_8 = text_replace_7.replace("(", " ( ")
text_replace_9 = text_replace_8.replace(")", " ) ")
text_replace_10 = text_replace_9.replace("/", " / ")
text_replace_11 = text_replace_10.replace("الله", "اللّٰـه")
text_split_list = text_replace_11.split()
count_number = []
letter_count_list = []
index_list = itertools.cycle(range(1, 4))
for letter_count in text_split_list:
if letter_count in interpunction_list:
letter_count_list.append(letter_count)
elif "ـ" in letter_count:
letter_count = len(letter_count) - 1
count_number.append(letter_count)
print(letter_count)
else:
letter_count = len(letter_count)
count_number.append(letter_count)
print(letter_count)
for count in count_number:
letter_count_list.append(letter_count * ".")
zip_list = zip(text_split_list, letter_count_list)
zip_list_result = list(zip_list)
for word, count in zip_list_result:
if ((len(word)) == 2 or word == "a" or word == "و") and not word in interpunction_list :
print(f" {{{{c{(next(index_list))}::{word}::{count}}}}}", end="")
elif word and count in interpunction_list:
print(word, end = "")
else:
print(f" {{{{c{(next(index_list))}::{word}::{count}}}}}", end="")
when I type كتب عليـ ـنا و علـ ـي
the return is {{c1::كتب::...}} {{c2::عليـ::...}} {{c3::ـنا::...}} {{c1::و::..}} {{c2::علـ::..}} {{c3::ـي::..}}
but it should be
{{c1::كتب::...}} {{c2::عليـ::...}} {{c3::ـنا::..}} {{c1::و::.}} {{c2::علـ::..}} {{c3::ـي::.}}
I add a print function the print the len() results and the result is correct but it add an extra dot in some case.
But when I type just a single "و" it does a correct len() function but when I input a whole sentence it add an extra dot and I don't know why.
please help
As the title suggests, i'm currently trying to add parts to the JPQL-query using collection-valued named parameters (:queryLst).
Function call:
List<PanelSet> psetLst = setRepository.getMaxZchnrGroupByLeftEight(p.getCustomerNumber(), p.getDrawingNumber(), queryLst);
queryLst:
// Is used to store values from scanned and convert them into parts of a query
ArrayList<String> queryLst = new ArrayList<>();
for (int i = 0; i < size1; i++) {
scanEdvRev = scanned.get(i).toString();
queryLst.set(i, "and left(a.drawingnumber, 8) != left('" + scanEdvRev + "', 8)");
}
SetRepository:
public interface SetRepository extends CrudRepository<PanelSet, Integer> {
#Query("select distinct max(a.drawingNumber) from PanelSet a "
+ "where a.customerNumber = :customerNumber "
+ "and a.drawingNumber != :drawingNumber (:queryLst) "
+ "group by left(a.drawingNumber, 8)")
List<PanelSet> getMaxZchnrGroupByLeftEight(#Param("customerNumber") String customerNumber,
#Param("drawingNumber") String drawingNumber,
#Param("queryLst") ArrayList<String> queryLst);
}
When i run the project i get the following exception:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 159 [select distinct max(a.drawingNumber) from com.asetronics.qis2.model.PanelSet a where a.customerNumber = :customerNumber and a.drawingNumber != :drawingNumber (:queryLst) group by left(a.drawingNumber, 8)]
I'm unsure whether my approach to this problem is the correct way of doing this and whether this exception is caused by a simple syntax error or by my usage of collection-valued named parameters.
I've followed this guide trying to solve the problem.
EDIT: I'm basically trying to add each String from ArrayList<String> queryLst to the parametrized query inside setRepository.
#Query("select distinct max(a.drawingNumber) from PanelSet a "
+ "where a.customerNumber = :customerNumber "
+ "and a.drawingNumber != :drawingNumber (:queryLst) "
+ "group by left(a.drawingNumber, 8)")
If successful, the query behind the function
List<PanelSet> getMaxZchnrGroupByLeftEight(#Param("customerNumber") String customerNumber,
#Param("drawingNumber") String drawingNumber,
#Param("queryLst") ArrayList<String> queryLst);
should look like this:
queryStr = "select distinct max(a.drawingNumber) from PanelSet a "
+ "where a.customerNumber = " + customerNumber + ""
+ "and a.drawingNumber != " + drawingNumber + "";
for (String s : queryLst) {
queryStr = queryStr + s;
}
queryStr = queryStr + " group by left(a.drawingNumber, 8)";
I hope this clarifies what i'm trying to do with queryLst.
It can't be done using your approach of passing in a list of query chunks.
The closest you'll get is by adding every possible condition to the query and provide values for all those conditions in a way that allows conditions to be ignored, typically by providing a null.
You code might look like this:
#Query("select distinct max(a.drawingNumber) from PanelSet a "
+ "where a.customerNumber = :customerNumber "
+ "and a.drawingNumber != :drawingNumber "
+ "and a.myTextColumn = coalesce(:myTextColumn, a.myTextColumn) "
+ "and a.myIntegerColumn = coalesce(:myIntegerColumn, a.myIntegerColumn) "
// etc for all possible runtime conditions
+ "group by left(a.drawingNumber, 8)")
List<PanelSet> getMaxZchnrGroupByLeftEight(
#Param("customerNumber") String customerNumber,
#Param("drawingNumber") String drawingNumber,
#Param("myTextColumn") String myTextColumn,
#Param("myIntegerColumn") Integer myIntegerColumn);
Passing null for myTextColumn or myIntegerColumn will allow that column to be any value (except null).
You'll have to find SQL that works for the type of conditions you have and the data type of the columns involved and whether nulls are allowed.
If passing nulls doesn't work, use a special value, perhaps blank for text columns and some "impossible" date like 2999-01-01 fir date columns etc and code the condition like:
and (a.myCol = :myCol or :myCol = '2999-01-01')
I made a loop for concatenating strings:
For cz As Integer = 0 To length - 1 Step +1
result += GetChar(a, index) + " * 2^" & length - 1 & " + "
index += 1
length -= 1
Next cz
Is it possible to not add the "+" on the loop's last step?
I want to use some operations on that result but when i have "+" as last char I can't.
String.Join will accomplish that for you if you pass it an enumerable of strings:
Dim result = String.Join(" + ",
a.Select(Function (c, i) c & " * 2^" & (a.Length - 1 - i)))
I am wanting to convert a 2d lua table into a string, then after converting it to a string convert it back into a table using that newly created string. It seems as if this process is called serialization, and is discussed in the below url, yet I am having a difficult time understanding the code and was hoping someone here had a simple table.toString and table.fromString function
http://lua-users.org/wiki/TableSerialization
I am using the following code in order to serialize tables:
function serializeTable(val, name, skipnewlines, depth)
skipnewlines = skipnewlines or false
depth = depth or 0
local tmp = string.rep(" ", depth)
if name then tmp = tmp .. name .. " = " end
if type(val) == "table" then
tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")
for k, v in pairs(val) do
tmp = tmp .. serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "")
end
tmp = tmp .. string.rep(" ", depth) .. "}"
elseif type(val) == "number" then
tmp = tmp .. tostring(val)
elseif type(val) == "string" then
tmp = tmp .. string.format("%q", val)
elseif type(val) == "boolean" then
tmp = tmp .. (val and "true" or "false")
else
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
end
return tmp
end
the code created can then be executed using loadstring(): http://www.lua.org/manual/5.1/manual.html#pdf-loadstring if you have passed an argument to 'name' parameter (or append it afterwards):
s = serializeTable({a = "foo", b = {c = 123, d = "foo"}})
print(s)
a = loadstring(s)()
The code lhf posted is a much simpler code example than anything from the page you linked, so hopefully you can understand it better. Adapting it to output a string instead of printing the output looks like:
t = {
{11,12,13},
{21,22,23},
}
local s = {"return {"}
for i=1,#t do
s[#s+1] = "{"
for j=1,#t[i] do
s[#s+1] = t[i][j]
s[#s+1] = ","
end
s[#s+1] = "},"
end
s[#s+1] = "}"
s = table.concat(s)
print(s)
The general idea with serialization is to take all the bits of data from some data structure like a table, and then loop through that data structure while building up a string that has all of those bits of data along with formatting characters.
How about a JSON module? That way you have also a better exchangeable data. I usually prefer dkjson, which also supports utf-8, where cmjjson won't.
Under the kong works this
local cjson = require "cjson"
kong.log.debug(cjson.encode(some_table))
Out of the kong should be installed package lua-cjson https://github.com/openresty/lua-cjson/
Here is a simple program which assumes your table contains numbers only. It outputs Lua code that can be loaded back with loadstring()(). Adapt it to output to a string instead of printing it out. Hint: redefine print to collect the output into a table and then at the end turn the output table into a string with table.concat.
t = {
{11,12,13},
{21,22,23},
}
print"return {"
for i=1,#t do
print"{"
for j=1,#t[i] do
print(t[i][j],",")
end
print"},"
end
print"}"
Assuming that:
You don't have loops (table a referencing table b and b referencing a)
Your tables are pure arrays (all keys are consecutive positive integers, starting on 1)
Your values are integers only (no strings, etc)
Then a recursive solution is easy to implement:
function serialize(t)
local serializedValues = {}
local value, serializedValue
for i=1,#t do
value = t[i]
serializedValue = type(value)=='table' and serialize(value) or value
table.insert(serializedValues, serializedValue)
end
return string.format("{ %s }", table.concat(serializedValues, ', ') )
end
Prepend the string resulting from this function with a return, store it on a .lua file:
-- myfile.lua
return { { 1, 2, 3 }, { 4, 5, 6 } }
You can just use dofile to get the table back.
t = dofile 'myfile.lua'
Notes:
If you have loops, then you will have
to handle them explicitly - usually with an extra table to "keep track" of repetitions
If you don't have pure arrays, then
you will have to parse t differently,
as well as handle the way the keys are rendered (are they strings? are they other tables? etc).
If you have more than just integers
and subtables, then calculating
serializedValue will be more
complex.
Regards!
I have shorter code to convert table to string but not reverse
function compileTable(table)
local index = 1
local holder = "{"
while true do
if type(table[index]) == "function" then
index = index + 1
elseif type(table[index]) == "table" then
holder = holder..compileTable(table[index])
elseif type(table[index]) == "number" then
holder = holder..tostring(table[index])
elseif type(table[index]) == "string" then
holder = holder.."\""..table[index].."\""
elseif table[index] == nil then
holder = holder.."nil"
elseif type(table[index]) == "boolean" then
holder = holder..(table[index] and "true" or "false")
end
if index + 1 > #table then
break
end
holder = holder..","
index = index + 1
end
return holder.."}"
end
if you want change the name just search all compileTable change it to you preferred name because this function will call it self if it detect nested table but escape sequence I don't know if it work
if you use this to create a lua executable file that output the table it will ge compilation error if you put new line and " sequence
this method is more memory efficient
Note:
Function not supported
User data I don't know
My solution:
local nl = string.char(10) -- newline
function serialize_list (tabl, indent)
indent = indent and (indent.." ") or ""
local str = ''
str = str .. indent.."{"
for key, value in pairs (tabl) do
local pr = (type(key)=="string") and ('["'..key..'"]=') or ""
if type (value) == "table" then
str = str..nl..pr..serialize_list (value, indent)..','
elseif type (value) == "string" then
str = str..nl..indent..pr..'"'..tostring(value)..'",'
else
str = str..nl..indent..pr..tostring(value)..','
end
end
str = str:sub(1, #str-1) -- remove last symbol
str = str..nl..indent.."}"
return str
end
local str = serialize_list(tables)
print('return '..nl..str)
is it possible to create a set of variables from a list of values using a closure??
the reason for asking this is to create some recursive functionality based on a list of (say) two three four or five parts
The code here of course doesn't work but any pointers would be helpful.then
def longthing = 'A for B with C in D on E'
//eg shopping for 30 mins with Fiona in Birmingham on Friday at 15:00
def breaks = [" on ", " in ", "with ", " for "]
def vary = ['when', 'place', 'with', 'event']
i = 0
line = place = with = event = ""
breaks.each{
shortline = longthing.split(breaks[i])
longthing= shortline[0]
//this is the line which obviously will not work
${vary[i]} = shortline[1]
rez[i] = shortline[1]
i++
}
return place + "; " + with + "; " + event
// looking for answer of D; C; B
EDIT>>
Yes I am trying to find a groovier way to clean up this, which i have to do after the each loop
len = rez[3].trim()
if(len.contains("all")){
len = "all"
} else if (len.contains(" ")){
len = len.substring(0, len.indexOf(" ")+2 )
}
len = len.replaceAll(" ", "")
with = rez[2].trim()
place = rez[1].trim()
when = rez[0].trim()
event = shortline[0]
and if I decide to add another item to the list (which I just did) I have to remember which [i] it is to extract it successfully
This is the worker part for then parsing dates/times to then use jChronic to convert natural text into Gregorian Calendar info so I can then set an event in a Google Calendar
How about:
def longthing = 'A for B with C in D on E'
def breaks = [" on ", " in ", "with ", " for "]
def vary = ['when', 'place', 'with', 'event']
rez = []
line = place = with = event = ""
breaks.eachWithIndex{ b, i ->
shortline = longthing.split(b)
longthing = shortline[0]
this[vary[i]] = shortline[1]
rez[i] = shortline[1]
}
return place + "; " + with + "; " + event
when you use a closure with a List and "each", groovy loops over the element in the List, putting the value in the list in the "it" variable. However, since you also want to keep track of the index, there is a groovy eachWithIndex that also passes in the index
http://groovy.codehaus.org/GDK+Extensions+to+Object
so something like
breaks.eachWithIndex {item, index ->
... code here ...
}