i want to remove separation characters from inbetween numbers in lua. For example: 19,300 -> 19300.
I am able to extract the two "parts" of the number using
a,b = string.match(amount, '(%d+),*(%d*)')
but have to store the results in two separate variables first. I would like to have a clean way of storing all capture groups as a concatinated, single variable, instead of having to do c=a..b in an extra step. Is there a way to achieve this?
You can simply remove all non-digits: local stripped = string.gsub( amount, '%D', '' ).
Related
I have a table of strings like this:
{
"1",
"1.5",
"3.13",
"1.2.5.7",
"2.5",
"1.3.5",
"2.2.5.7.10",
"1.17",
"1.10.5",
"2.3.14.9",
"3.5.21.9.3",
"4"
}
And would like to sort that like this:
{
"1",
"1.2.5.7",
"1.3.5",
"1.5",
"1.10.5",
"1.17",
"2.2.5.7.10",
"2.3.14.9",
"2.5",
"3.5.21.9.3",
"3.13",
"4"
}
How do I sort this in Lua? I know that table.sort() will be used, I just don't know the function (second parameter) to use for comparison.
Given your requirements, you probably want something like natural sort order. I described several possible solution as well as their impact on the results in a blog post.
The simplest solution may look like this (below), but there are 5 different solutions listed with different complexity and the results:
function alphanumsort(o)
local function padnum(d) return ("%03d%s"):format(#d, d) end
table.sort(o, function(a,b)
return tostring(a):gsub("%d+",padnum) < tostring(b):gsub("%d+",padnum) end)
return o
end
table.sort sorts ascending by default. You don't have to provide a second parameter then. As you're sorting strings Lua will compare the strings character by character. Hence you must implement a sorting function that tells Lua which comes first.
I just don't know the function (second parameter) to use for
comparison.
That's why people wrote the Lua Reference Manual
table.sort (list [, comp])
Sorts the list elements in a given order, in-place, from list1 to
list[#list]. If comp is given, then it must be a function that
receives two list elements and returns true when the first element
must come before the second in the final order, so that, after the
sort, i <= j implies not comp(list[j],list[i]). If comp is not given,
then the standard Lua operator < is used instead.
The comp function must define a consistent order; more formally, the
function must define a strict weak order. (A weak order is similar to
a total order, but it can equate different elements for comparison
purposes.)
The sort algorithm is not stable: Different elements considered equal
by the given order may have their relative positions changed by the
sort.
Think about how you would do it with pen an paper. You would compare each number segment. As soon as a segment is smaller than the other you know this number comes first.
So a solution would probably require you to get those segments for the strings, convert them to numbers so you can compare their values...
Our task is create a table, and read values to the table using a loop. Print the values after the process is complete. - Create a table. - Read the number of values to be read to the table. - Read the values to the table using a loop. - Print the values in the table using another loop. for this we had written code as
local table = {}
for value in ipairs(table) do
io.read()
end
for value in ipairs(table) do
print(value)
end
not sure where we went wrong please help us. Our exception is
Input (stdin)
3
11
22
abc
Your Output (stdout)
~ no output ~
Expected Output
11
22
abc
Correct Code is
local table1 = {}
local x = io.read()
for line in io.lines() do
table.insert(table1, line)
end
for K, value in ipairs(table1) do
print(value)
end
Let's walk through this step-by-step.
Create a table.
Though the syntax is correct, table is a reserved pre-defined global name in Lua, and thus cannot should not be declared a variable name to avoid future issues. Instead, you'll need to want to use a different name. If you're insistent on using the word table, you'll have to distinguish it from the function global table. The easiest way to do this is change it to Table, as Lua is a case-sensitive language. Therefore, your table creation should look something like:
local Table = {}
Read values to the table using a loop.
Though Table is now established as a table, your for loop is only iterating through an empty table. It seems your goal is to iterate through the io.read() instead. But io.read() is probably not what you want here, though you can utilize a repeat loop if you wish to use io.read() via table.insert. However, repeat requires a condition that must be met for it to terminate, such as the length of the table reaching a certain amount (in your example, it would be until (#Table == 4)). Since this is a task you are given, I will not provide an example, but allow you to research this method and use it to your advantage.
Print the values after the process is complete.
You are on the right track with your printing loop. However, it must be noted that iterating through a table always returns two results, an index and a value. In your code, you would only return the index number, so your output would simply return:
1
2
3
4
If you are wanting the actual values, you'll need a placeholder for the index. Oftentimes, the placeholder for an unneeded variable in Lua is the underscore (_). Modify your for loop to account for the index, and you should be set.
Try modifying your code with the suggestions I've given and see if you can figure out how to achieve your end result.
Edited:
Thanks, Piglet, for corrections on the insight! I'd forgotten table itself wasn't a function, and wasn't reserved, but still bad form to use it as a variable name whether local or global. At least, it's how I was taught, but your comment is correct!
I have to select group of cases starting with specific numbers in multiple variables.
I am using this
CHAR.SUBSTR(variable1,1,x) ="y" | CHAR.SUBSTR(variable2,1,x) ="y" .............| CHAR.SUBSTR(variable40,1,x) ="y".
(x is number of character,y is characters I am choosing) the variables are named similar with just the number 1 to 40 being different
it works but problem is there are 40 variables and code is very length.
any elegant way to write it? like variable1 THRU variable 40?
You can loop through the variables and then select. Like this:
do repeat vr=variable1 to variable40.
if CHAR.SUBSTR(vr,1,1)="y" keep_this=1.
end repeat.
select if keep_this=1.
after running the loop, if any of the variables starts with "y" then the line will be marked with 1 in the variable keep_this. Now you can select only cases where keep_this=1.
I have an input string that looks something like this:
HLI6Ch60000Ch500C0Ch46400Ch30000Ch21888Ch10E79CS07LCU3Ch37880Ch27800Ch16480CS8CA00000000000000000000
Now I don't care about the part that follows the last letter A, it'll always be A and exactly 20 numbers that are of no use to me. I do, however, need the part before the last letter A, and ideally, I'd need it to be separated into two different captures, just like this:
1: HLI6Ch60000Ch500C0Ch46400Ch30000Ch21888Ch10E79CS07
2: LCU3Ch37880Ch27800Ch16480CS8C
The only way to identify these matches is that they end with characters CS followed by two hexadecimal characters. I thought that a regular expression like (.+?CS.{2})+ (or (.+?CS[[:xdigit:]]{2})+) would do the job but when tried on www.regex101.com, it only captures the last group and gives the following warning:
Note: A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data
Which I thought suggests that I should use regular expression like ((.+?CS.{2})+) instead and I mean – sure, now I get two captures, but they look like this:
1: HLI6Ch60000Ch500C0Ch46400Ch30000Ch21888Ch10E79CS07LCU3Ch37880Ch27800Ch16480CS8C
2: LCU3Ch37880Ch27800Ch16480CS8C
Meaning the first one is… slightly longer than I'd like it to be. If it helps in any way, I should point out that the final regular expression will be part of an iOS application so an instance of NSRegularExpression class will be used – not sure if that's a helpful information at all, it's just that I know that NSRegularExpression doesn't support every part of the world of regular expressions.
(.+?CS.{2})
You can direclty use this.See demo.Grab the group or capture.
https://regex101.com/r/vD5iH9/68
It doesn't seem like you need a capturing group at all:
(?:(?!CS[0-9A-F]{2}).)+CS[0-9A-F]{2}
will match all strings that end in CS + 2 hex digits.
Test it live on regex101.com.
Explanation:
(?: # Start a group.
(?!CS[0-9A-F]{2}) # Make sure we can't match CSff here,
. # if so, match any character.
)+ # Do this at least once.
CS[0-9A-F]{2} # Then match CSff.
Change your regex to,
(.+?CS[[:xdigit:]]{2})
DEMO
You don't need to put the regex inside another capturing group and make it to repeat one or more times. Just print the group index 1 to get your desired output.
First of all: I'm an inexperienced coder and just started reading PiL. I only know a thing or two but I'm fast learning and understanding. This method is really unnecessary but I sort of want to give myself a hard time in order to learn more.
Okay so for testing and for getting to know the language more, I'm trying to grab two different values from two different files and storing them in tables
local gamemap = file.Read("addons/easymap/data/maplist.txt", "GAME")
local mapname = string.Explode( ",", gamemap )
local mapid = file.Read("addons/easymap/data/mapid.txt", "GAME")
local id = string.Explode( ",", mapid )
I'm grabbing two values which in the end are mapname and id
Once I have them, I know that using
for k, v in pairs(mapname)
It will give specific values to the data taken from the file, or at least assign them.
But what I need to do with the both tables is that if there is certain map in the server, check for the value in the table unless the map name is nil and then once having the name, grab the value of that map and match it with the id of the other file.
For example, I have in the maplist.txt file gm_construct and it is the first entry [1] and its corresponding id in mapid.txt lets say it is 54321 and it is also the first entry [1].
But now I must check the server's current map with game.GetMap function, I have that solved and all, I grab the current map, match it with the mapname table and then check for its corresponding value in the id table, which would be gm_construct = 1.
For example it would be something like
local mapdl = game.GetMap()
local match = mapname[mapdl]
if( match != nil )then --supposing the match isn't nil and it is in the table
--grab its table value, lets say it is 1 and match it with the one in the id table
It is a more complex version of this http://pastebin.com/3652J8Pv
I know it is unnecessary but doing this script will give me more options to expand the script further.
TL;DR: I need to find a function that lets me match two values coming from different tables and files, but in the end they are in the same order ([1] = [1]) in both files. Or a way to fetch a full table from another file. I don't know if a table can be loaded globally and then grabbed by another file to use it in that file.
I'm sorry if I'm asking too much, but where I live, if you want to learn to program, you have to do it on your own, no schools have classes or anything similar, at least not until University, and I'm far away from even finishing High School.
Edit: this is intended to be used on Garry's mod. The string.Explode is explained here: http://wiki.garrysmod.com/page/string/Explode
It basically separates phrases by a designated character, in this case, a comma.
Okay. If I understand correctly... You have 2 Files with data.
One with Map Names
gm_construct,
gm_flatgrass,
de_dust2,
ttt_waterworld
And One with IDs, Numbers, Whataver (related to the entries at the same position in the Map Names File
1258,
8592,
1354,
2589
And now you want to find the ID of the current Map, right?
Here is your Function
local function GetCurrentMapID()
-- Get the current map
local cur_map = game.GetMap()
-- Read the Files and Split them
local mapListRaw = file.Read("addons/easymap/data/maplist.txt", "GAME")
local mapList= string.Explode(",", mapListRaw)
local mapIDsRaw = file.Read("addons/easymap/data/mapid.txt", "GAME")
local mapIDs = string.Explode(",", mapIDsRaw)
-- Iterate over the whole map list
for k, v in pairs(mapList) do
-- Until you find the current map
if (v == cur_map) then
-- then return the value from mapIDs which is located at the same key (k)
return mapIDs[k]
end
end
-- Throw a non-breaking error if the current map is not in the Maplist
ErrorNoHalt( "Current map is not registered in the Maplist!\n" )
end
Code could have errors 'cause I couldn't test it. Pls Comment with error if so.
Source: My Experience and the GMod Wiki