I am working on a project where I need to find the integer value substituted from a character which is either 'K' 'M' or 'B'.
I am trying to find the best way for a user to input a string such as "1k" "12k" "100k" and to receive the value back in the appropriate way. Such as a user entering "12k" and I would receive "12000".
I am new to Lua, and I am not that great at string patterns.
if (string.match(text, 'k')) then
print(text)
local test = string.match(text, '%d+')
print(test)
end
local text = "1k"
print(tonumber((text:lower():gsub("[kmb]", {k="e3"}))))
I don't know what factors you use for M and B. What is that supposed to be? Million and billion?
I suggest you use the international standard. kilo (k), mega (M), giga (G) instead.
Then it would look like so:
local text = "1k"
print(tonumber((text:gsub("[mkMG]", {m = "e-3", k="e3", M="e6", G="e9"})))) --and so on
You can match the pattern as something like (%d+)([kmb]) to get the number and the suffix separately. Then just tonumber the first part and map the latter to a factor (using a table, for example) and multiply it with your result.
local factors = { k=1e3, m=1e6, --[and so on]] }
local num, suffix = string.match(text, '(%d+)([kmb])')
local result = tonumber(num) * factors[suffix]
Related
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+)')
I need this for a game server using Lua..
I would like to be able to save all combinations of a name
into a string that can then be used with:
if exists (string)
example:
ABC_-123
aBC_-123
AbC_-123
ABc_-123
abC_-123
etc
in the game only numbers, letters and _ - . can be used as names.
(A_B-C, A-B.C, AB_8 ... etc)
I understand the logic I just don't know how to code it:D
0-Lower
1-Upper
then
000
001
etc
You can use recursive generator. The first parameter contains left part of the string generated so far, and the second parameter is the remaining right part of the original string.
function combinations(s1, s2)
if s2:len() > 0 then
local c = s2:sub(1, 1)
local l = c:lower()
local u = c:upper()
if l == u then
combinations(s1 .. c, s2:sub(2))
else
combinations(s1 .. l, s2:sub(2))
combinations(s1 .. u, s2:sub(2))
end
else
print(s1)
end
end
So the function is called in this way.
combinations("", "ABC_-123")
You only have to store intermediate results instead of printing them.
If you are interested only in the exists function then you don't need all combinations.
local stored_string = "ABC_-123"
function exists(tested_string)
return stored_string:lower() == tested_string:lower()
end
You simply compare the stored string and the tested string in case-insensitive way.
It can be easily tested:
assert(exists("abC_-123"))
assert(not exists("abd_-123"))
How to do this?
There's native function in Lua to generate all permutations of a string, but here are a few things that may prove useful.
Substrings
Probably the simplest solution, but also the least flexible. Rather than combinations, you can check if a substring exists within a given string.
if str:find(substr) then
--code
end
If this solves your problem, I highly reccomend it.
Get all permutations
A more expensive, but still a working solution. This accomplishes nearly exactly what you asked.
function GetScrambles(str, tab2)
local tab = {}
for i = 1,#str do
table.insert(tab, str:sub(i, i))
end
local tab2 = tab2 or {}
local scrambles = {}
for i = 0, Count(tab)-1 do
local permutation = ""
local a = Count(tab)
for j = 1, #tab do
tab2[j] = tab[j]
end
for j = #tab, 1, -1 do
a = a / j
b = math.floor((i/a)%j) + 1
permutation = permutation .. tab2[b]
tab2[b] = tab2[j]
end
table.insert(scrambles, permutation)
end
return scrambles
end
What you asked
Basically this would be exactly what you originally asked for. It's the same as the above code, except with every substring of the string.
function GetAllSubstrings(str)
local substrings = {}
for i = 1,#str do
for ii = i,#str do
substrings[#substrings+1]=str:sub(ii)
end
end
return substrings
end
Capitals
You'd basically have to, with every permutation, make every possible combination of capitals with it.
This shouldn't be too difficult, I'm sure you can code it :)
Are you joking?
After this you should probably be wondering. Is all of this really necessary? It seems like a bit much!
The answer to this lies in what you are doing. Do you really need all the combinations of the given characters? I don't think so. You say you need it for case insensitivity in the comments... But did you know you could simply convert it into lower/upper case? It's very simple
local str = "hELlO"
print(str:lower())
print(str:upper())
This is HOW you should store names, otherwise you should leave it case sensitive.
You decide
Now YOU pick what you're going to do. Whichever direction you pick, I wish you the best of luck!
Suppose I have a factor variable with labels "a" "b" and "c" and want to see which observations have a label of "b". Stata refuses to parse
gen isb = myfactor == "b"
Sure, there is literally a "type mismatch", since my factor is encoded as an integer and so cannot be compared to the string "b". However, it wouldn't kill Stata to (i) perform the obvious parse or (ii) provide a translator function so I can write the comparison as label(myfactor) == "b". Using decode to (re)create a string variable defeats the purpose of encoding, which is to save space and make computations more efficient, right?
I hadn't really expected the comparison above to work, but I at least figured there would be a one- or two-line approach. Here is what I have found so far. There is a nice macro ("extended") function that maps the other way (from an integer to a label, seen below as local labi: label ...). Here's the solution using it:
// sample data
clear
input str5 mystr int mynum
a 5
b 5
b 6
c 4
end
encode mystr, gen(myfactor)
// first, how many groups are there?
by myfactor, sort: gen ng = _n == 1
replace ng = sum(ng)
scalar ng = ng[_N]
drop ng
// now, which code corresponds to "b"?
forvalues i = 1/`=ng'{
local labi: label myfactor `i'
if "b" == "`labi'" {
scalar bcode = `i'
break
}
}
di bcode
The second step is what irks me, but I'm sure there's a also faster, more idiomatic way of performing the first step. Can I grab the length of the label vector, for example?
An example:
clear all
set more off
sysuse auto
gen isdom = 1 if foreign == "Domestic":`:value label foreign'
list foreign isdom in 1/60
This creates a variable called isdom and it will equal 1 if foreigns's value label is equal to "Domestic". It uses an extended macro function.
From [U] 18.3.8 Macro expressions:
Also, typing
command that makes reference to `:extended macro function'
is equivalent to
local macroname : extended macro function
command that makes reference to `macroname'
This explains one of the two : in the offered syntax. The other can be explained by
... to specify value labels directly in an expression, rather than through
the underlying numeric value ... You specify the label in double quotes
(""), followed by a colon (:), followed by the name of the value
label.
The quote is from Stata tip 14: Using value labels in expressions, by Kenneth Higbee, The Stata Journal (2004). Freely available at http://www.stata-journal.com/sjpdf.html?articlenum=dm0009
Edit
On computing the number of distinct observations, another way is:
by myfactor, sort: gen ng = _n == 1
count if ng
scalar sc_ng = r(N)
display sc_ng
But yours is fine. In fact, it is documented here: http://www.stata.com/support/faqs/data-management/number-of-distinct-observations/, along with more methods and comments.
I need to use Redis in a project I am using and was wondering if there was anyway to do proper mathmatic operations and comparisons on floats using LUA scripts(or anyway really). For example, I have a field, and need to multiply it by another field, and compare it to a third field. For example
local staticVal = .2
local dynamicVal2 = redis.pcall('GET', 'dynamicVal2')
local calcVal = dynamicVal * staticVal
local compareVal = 100
if calcVal < compareVal then
return false
else
return true
Is there a possible way to do this, or do I have to just make the GET calls from another language and do the comparison there?
Thank you
Edit:
Or the ability to just compare floating point numbers would be helpful. It seems that a dictionary comparison is done rather than a numerical comparison.
Edit 2:
SET val1 10.5
SET val2 3.5
EVAL "local val1 = redis.pcall('GET','val1'); local val2 = redis.pcall('GET','val2'); if val1 > val2 then return val1 else return val2 end" 0
It seems that a dictionary comparison is done rather than a numerical comparison.
local val1 = redis.pcall('GET','val1');
local val2 = redis.pcall('GET','val2');
if val1 > val2 then ...
Check the type of val1 and val2 (e.g. print(type(val1))). My guess is that they are strings, which is why you're getting a lexical comparison rather than a numerical one.
Lua's native number type is floating point and it has no problem comparing them. If your values are indeed strings, you just need to convert them into numbers (e.g. tonumber(val1)) before comparing them.
Of course you can: in Lua, all the numbers are floats. It is actually more difficult to work with large integer values than with floats (due to the internal numbers representation).
From redis-cli:
set dynamicVal2 100000.0
eval "local staticVal = .2 ; local dynamicVal = tonumber(redis.call('GET', 'dynamicVal2')); local calcVal = dynamicVal * staticVal; local compareVal = 100; if calcVal < compareVal then return false; else return true; end;" 0
(integer) 1
Now using Lua for the example you gave is not that useful: what is done with Lua on server-side could be easily done on client-side with similar efficiency. And it is actually better to do it on client-side if you can. Like with many other data stores, the more you can do on client-side for the same number of roundtrips, the best it is.
It would have been more useful if the Lua script was effectively used to avoid multiple roundtrips to Redis.
I need a base converter function for Lua. I need to convert from base 10 to base 2,3,4,5,6,7,8,9,10,11...36 how can i to this?
In the string to number direction, the function tonumber() takes an optional second argument that specifies the base to use, which may range from 2 to 36 with the obvious meaning for digits in bases greater than 10.
In the number to string direction, this can be done slightly more efficiently than Nikolaus's answer by something like this:
local floor,insert = math.floor, table.insert
function basen(n,b)
n = floor(n)
if not b or b == 10 then return tostring(n) end
local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local t = {}
local sign = ""
if n < 0 then
sign = "-"
n = -n
end
repeat
local d = (n % b) + 1
n = floor(n / b)
insert(t, 1, digits:sub(d,d))
until n == 0
return sign .. table.concat(t,"")
end
This creates fewer garbage strings to collect by using table.concat() instead of repeated calls to the string concatenation operator ... Although it makes little practical difference for strings this small, this idiom should be learned because otherwise building a buffer in a loop with the concatenation operator will actually tend to O(n2) performance while table.concat() has been designed to do substantially better.
There is an unanswered question as to whether it is more efficient to push the digits on a stack in the table t with calls to table.insert(t,1,digit), or to append them to the end with t[#t+1]=digit, followed by a call to string.reverse() to put the digits in the right order. I'll leave the benchmarking to the student. Note that although the code I pasted here does run and appears to get correct answers, there may other opportunities to tune it further.
For example, the common case of base 10 is culled off and handled with the built in tostring() function. But similar culls can be done for bases 8 and 16 which have conversion specifiers for string.format() ("%o" and "%x", respectively).
Also, neither Nikolaus's solution nor mine handle non-integers particularly well. I emphasize that here by forcing the value n to an integer with math.floor() at the beginning.
Correctly converting a general floating point value to any base (even base 10) is fraught with subtleties, which I leave as an exercise to the reader.
you can use a loop to convert an integer into a string containting the required base. for bases below 10 use the following code, if you need a base larger than that you need to add a line that mapps the result of x % base to a character (usign an array for example)
x = 1234
r = ""
base = 8
while x > 0 do
r = "" .. (x % base ) .. r
x = math.floor(x / base)
end
print( r );