I am looking for a Lua find and replace logic - lua

enter image description here
I just started working on lua scripting since a week. I have a lua file where in the logic needs to be written for a certain condition.
The condition when gets triggered
it does an iteration on one of the fields to change value from
(ABC123-XYZ) to this value
(ABC123#1-XYZ) and it keeps increasing whenever iterations happens (ABC123#2-XYZ)
I need to run a function that removes the # followed by number to change it back to (ABC123-XYZ). Looking for any advice!
Edit 1:
Below is the updated code that is written Thanks to #Piglet
I have another scenario if therr are two hashes in the variable.
local x = 'BUS144611111-PNB_00#80901#1555-122TRNHUBUS'
local b = x:gsub("#%d+","")
function remove_char(a) a=a:gsub("#%d+","")
return a;
end if string.match(x,"#")
then print('function')
print(remove_char(x));
else print(x);
end
Expected output should be
x = 'BUS144611111-PNB_00#80901-122TRNHUBUS' for the aforesaid variable

local a = "ABC123#1-XYZ"
local b = a:gsub("#%d+", "")
this will remove any # followed by or one more digits from your string.

Related

Issue returning desired data with Lua

Wondering if I could get some help with this:
function setupRound()
local gameModes = {'mode 1','mode 2','mode 3'} -- Game modes
local maps = {'map1','map2','map3'}
--local newMap = maps[math.random(1,#maps)]
local mapData = {maps[math.random(#maps)],gameModes[math.random(#gameModes)]}
local mapData = mapData
return mapData
end
a = setupRound()
print(a[1],a[2]) --Fix from Egor
What the problem is:
`
When trying to get the info from setupRound() I get table: 0x18b7b20
How I am trying to get mapData:
a = setupRound()
print(a)
Edit:
Output Issues
With the current script I will always the the following output: map3 mode 2.
What is the cause of this?
Efficiency; is this the best way to do it?
While this really isn't a question, I just wanted to know if this method that I am using is truly the most efficient way of doing this.
First of all
this line does nothing useful and can be removed (it does something, just not something you'd want)
local mapData = mapData
Output Issues
The problem is math.random. Write a script that's just print(math.random(1,100)) and run it 100 times. It will print the same number each time. This is because Lua, by default, does not set its random seed on startup. The easiest way is to call math.randomseed(os.time()) at the beginning of your program.
Efficiency; is this the best way to do it?
Depends. For what you seem to want, yes, it's definitely efficient enough. If anything, I'd change it to the following to avoid magic numbers which will make it harder to understand the code in the future.
--- etc.
local mapData = {
map = maps[math.random(#maps)],
mode = gameModes[math.random(#gameModes)]
}
-- etc.
print(a.map, a.mode)
And remember:
Premature optimization is the root of all evil.
— Donald Knuth
You did very good by creating a separate function for generating your modes and maps. This separates code and is modular and neat.
Now, you have your game modes in a table modes = {} (=which is basically a list of strings).
And you have your maps in another table maps = {}.
Each of the table items has a key, that, when omitted, becomes a number counted upwards. In your case, there are 3 items in modes and 3 items in maps, so keys would be 1, 2, 3. The key is used to grab a certain item in that table (=list). E.g. maps[2] would grab the second item in the maps table, whose value is map 2. Same applies to the modes table. Hence your output you asked about.
To get a random game mode, you just call math.random(#mode). math.random can accept up to two parameters. With these you define your range, to pick the random number from. You can also pass a single parameter, then Lua assumes to you want to start at 1. So math.random(3) becomes actually math.random(1, 3). #mode in this case stand for "count all game modes in that table and give me that count" which is 3.
To return your chosen map and game mode from that function we could use another table, just to hold both values. This time however the table would have different keys to access the values inside it; namely "map" and "mode".
Complete example would be:
local function setupRound()
local modes = {"mode 1", "mode 2", "mode 3"} -- different game modes
local maps = {"map 1", "map 2", "map 3"} -- different maps
return {map = maps[math.random(#maps)], mode = modes[math.random(#modes)]}
end
for i = 1, 10 do
local freshRound = setupRound()
print(freshRound.map, freshRound.mode)
end

splitting lua strings into variables

I am pretty new to this, so I hope you can give me a hand.
I am programming lights, and what I like to do is take a variable from my lighting desk (a text string called "4 Mythos Stage") and split is into different variables.
to get the variables from the desk I use:
return function ()
local Layer1 = gma.user.getvar("Layer1") -- I placed "4 Mythos Stage" variable in Layer1
gma.feedback(Layer1) -- gives feedback 4 Mythos Stage
end
Now I would like to split the string into 3 new local variables named:
local number -- should produce 4
local fixturetype -- should produce Mythos
local location -- should produce Stage
i tried the following:
local number = string.match('Layer1', '%d+')
local fixturetype = string.match('Layer1', '%a+')
local location = string.match('Layer1', '%a+')
this didn't work, so can somebody please help me in the right direction. I would be really greatful.
with kind regards,
Martijn
You can assign all three variables at the same time, because Lua has multiple returns and multiple assignment. Put parentheses around each of your patterns in order to return them as captures, and combine them into a single pattern with spaces between them:
local number, fixturetype, location = string.match(Layer1, '(%d+) (%a+) (%a+)')
In case you will be using multiple spaces or tabs between the items, this pattern would be better:
local number, fixturetype, location = string.match(Layer1, '(%d+)[ \t]+(%a+)[ \t]+(%a+)')
The reason why your attempt didn't work is because string.match('Layer1', '%d+') is searching inside 'Layer1' (a string) instead of Layer1 (a variable).
But even if you corrected that, you would get 'Mythos' every time you called string.match(Layer1, '%a+') (where Layer1 == '4 Mythos Stage'). string.match always starts from the beginning of the string, unless you supply an index in the third parameter: string.match(Layer1, '%a+', 9) --> 'Stage'.
A robust solution for this task is to split the string into three "words", a word being a sequence of non-whitespace characters:
local number, fixturetype, location = string.match(Layer1, '(%S+)%s+(%S+)%s+(%S+)')

intersect multiple sets with lua script using redis.call("sinter", ...) command

I want to intersect multiple sets (2 or more). The number of sets to be intersected are passed as ARGV from command line. As number of sets are being passed from command-line. So the number of arguments in redis.call() function are uncertain.
How can I do so using redis.call() function in Lua script.
However, I have written a script which has algo like:
Accepting the number of sets to be intersected in the KEYS[1].
Intersecting the first two sets by using setIntersected = redis.call(ARGV[1], ARGV[2]).
Running a loop and using setIntersected = redis.call("sinter", tostring(setIntersected), set[i])
Then finally I should get the intersected set.
The code for the above algorithm is :
local noOfArgs = KEYS[1] -- storing the number of arguments that will get passed from cli
--[[
run a loop noOfArgs time and initialize table elements, since we don't know the number of sets to be intersected so we will use Table (arrays)
--]]
local setsTable = {}
for i = 1, noOfArgs, 1 do
setsTable[i] = tostring(ARGV[i])
end
-- now find intersection
local intersectedVal = redis.call("sinter", setsTable[1], setsTable[2]) -- finding first intersection because atleast we will have two sets
local new_updated_set = ""
for i = 3, noOfArgs, 1 do
new_updated_set = tostring(intersectedVal)
intersectedVal = redis.call("sinter", new_updated_set, setsTable[i])
end
return intersectedVal
This script works fine when I pass two sets using command-line.
EG:
redic-cli --eval scriptfile.lua 2 , points:Above20 points:Above30
output:-
1) "playerid:1"
2) "playerid:2"
3) "playerid:7"
Where points:Above20 and points:Above30 are sets. This time it doesn't go through the for loop which starts from i = 3.
But when I pass 3 sets then I always get the output as:
(empty list or set)
So there is some problem with the loop I have written to find intersection of sets.
Where am I going wrong? Is there any optimized way using which I can find the intersection of multiple sets directly?
What you're probably looking for is the elusive unpack() Lua command, which is equivalent to what is known as the "Splat" operator in other languages.
In your code, use the following:
local intersectedVal = redis.call("sinter", unpack(setsTable))
That said, SINTER is variadic and can accept multiple keys as arguments. Unless your script does something in addition to just intesects, you'd be better use that instead.

Can't modify loop-variable in lua [duplicate]

This question already has answers here:
Lua for loop reduce i? Weird behavior [duplicate]
(3 answers)
Closed 7 years ago.
im trying this in lua:
for i = 1, 10,1 do
print(i)
i = i+2
end
I would expect the following output:
1,4,7,10
However, it seems like i is getting not affected, so it gives me:
1,2,3,4,5,6,7,8,9,10
Can someone tell my a bit about the background concept and what is the right way to modify the counter variable?
As Colonel Thirty Two said, there is no way to modify a loop variable in Lua. Or rather more to the point, the loop counter in Lua is hidden from you. The variable i in your case is merely a copy of the counter's current value. So changing it does nothing; it will be overwritten by the actual hidden counter every time the loop cycles.
When you write a for loop in Lua, it always means exactly what it says. This is good, since it makes it abundantly clear when you're doing looping over a fixed sequence (whether a count or a set of data) and when you're doing something more complicated.
for is for fixed loops; if you want dynamic looping, you must use a while loop. That way, the reader of the code is aware that looping is not fixed; that it's under your control.
When using a Numeric for loop, you can change the increment by the third value, in your example you set it to 1.
To see what I mean:
for i = 1,10,3 do
print(i)
end
However this isn't always a practical solution, because often times you'll only want to modify the loop variable under specific conditions. When you wish to do this, you can use a while loop (or if you want your code to run at least once, a repeat loop):
local i = 1
while i < 10 do
print(i)
i = i + 1
end
Using a while loop you have full control over the condition, and any variables (be they global or upvalues).
All answers / comments so far only suggested while loops; here's two more ways of working around this problem:
If you always have the same step size, which just isn't 1, you can explicitly give the step size as in for i =start,end,stepdo … end, e.g. for i = 1, 10, 3 do … or for i = 10, 1, -1 do …. If you need varying step sizes, that won't work.
A "problem" with while-loops is that you always have to manually increment your counter and forgetting this in a sub-branch easily leads to infinite loops. I've seen the following pattern a few times:
local diff = 0
for i = 1, n do
i = i+diff
if i > n then break end
-- code here
-- and to change i for the next round, do something like
if some_condition then
diff = diff + 1 -- skip 1 forward
end
end
This way, you cannot forget incrementing i, and you still have the adjusted i available in your code. The deltas are also kept in a separate variable, so scanning this for bugs is relatively easy. (i autoincrements so must work, any assignment to i below the loop body's first line is an error, check whether you are/n't assigning diff, check branches, …)

How to fix "attempt to concatenate table and string"?

I asked a question similar to this the other day, but another bug popped up "attempt to concatenate table and string"
local questions={
EN={
Q2={"Who is the lead developer of Transformice?","Tigrounette"},
Q4={"What is Eminem's most viewed song on youtube?","I love the way you lie"},
Q6={"What is the cubic root of 27?","3"},
Q8={"What are the first 3 digits of Pi","3.141"},
Q10={"What is the most populated country?","China"},
Q12={"What is the plural of the word 'Person'?","People"},
Q14={"Entomology is the science that studies ...?","Insects"},
Q16={"Who was the creator of the (bot ran) minigame fight?","Cptp"},
Q18={"The ozone layer restricts ... radiation","Ultraviolet"},
Q20={"Filaria is caused by ...","Mosquitos"}
}
local main = questions.EN["Q"..math.random(1,20)].."%s" -- bug here
local current_answer_en = string.gsub(current_question_en,1,2)
What type of object is questions.EN["Q"..math.random(1,20)]? Say random is 15, what type of object is questions.EN["Q6"]? It is a {"What is the cubic root of 27?","3"}, which is a table, which Lua doesn't know how to concatenate with a string ("%s" in your case). If you want to concatenate with the first item of this table, then
local main = questions.EN["Q"..math.random(1,20)][1] .. "%s"
Note however that you will need the "random with step" function that I posted in math.random function with step option?, otherwise you could get that the table EN["Q"..something] is nil (if the random number is an odd number, in the code you posted).
Note sure what you are trying to do with current_question_en but if you are trying to extract the question and answer you could do something like this:
local QA = questions.EN["Q"..math.random(1,20)] -- this is a table
local question, answer = QA[1], QA[2]
The other option is that you build your table like this:
local questions={
EN={
Q2={q="Who is ..?", a="Tigrounette"},
Q4={q="What is ...?", a="I love the way you lie"},
...
}
}
Then you could use
local QA = questions.EN["Q"..math.random(1,20)] -- this is a table
print("The question:", QA.q)
print("The answer:", QA.a)
Not sure what you're trying to do with string.gsub but it does not take integers as 2nd and 3rd args.

Resources