from list to string and back to list - erlang

I have read a multiline file and converted it to a list with the following code:
Lines = string:tokens(erlang:binary_to_list(Binary), "\n"),
I converted it to a string to do some work on it:
Flat = string:join(Lines, "\r\n"),
I finished working on the string and now I need to convert it back to a multiline list, I tried to repeat the first snippet shown above but that never worked, I tried string:join and that didnt work.. how do i convert it back to a list just like it used to be (although now modified)?

Well that depends on the modifications you made on the flattened string.
string:tokens/2 will always explode a string using the separator you provide. So as long as your transformation preserves a specific string as separator between the individual substrings there should be no problem.
However, if you do something more elaborate and destructive in your transformation then the only way is to iterate on the string manually and construct the individual substrings.

Your first snippet above contains a call to erlang:binary_to_list/1 which first converts a binary to a string (list) which you then split with the call to string:tokens/2 which then join together with string:join/2. The result of doing the tokens then join as you have written it seems to be to convert it from a string containing lines separated by \n into one containing lines separated by \r\n. N.B. that this is a flat list of characters.
Is this what you intended?
What you should do now depends on what you mean by "I need to convert it back to a multiline list". Do you mean everything in a single list of characters (string), or in a nested list of lines where each line is a list of characters (string). I.e. if you ended up with
"here is line 1\r\nhere is line 2\r\nhere is line 3\r\n"
this already is a multiline line list, or do you mean
["here is line 1","here is line 2","here is line 3"]
Note that each "string" is itself a list of characters. What do you intend to do with it afterwards?

You have your terms confused. A string in any language is a sequence of integer values corresponding to a human-readable characters. Whether the representation of the value is a binary or a list does not matter, both are technically strings because of the data they contain.
That being said, you converted a binary string to a list string in your first set of instructions. To convert a list into a binary, you can call erlang:list_to_binary/1, or erlang:iolist_to_binary/1 if your list is not flat. For instance:
BinString = <<"this\nis\na\nstring">>.
ListString = "this\nis\na\nstring" = binary_to_list(BinString).
Words = ["this", "is", "a", "string"] = string:tokens(ListString, "\n").
<<"thisisastring">> = iolist_to_binary(Words).
Rejoined = "this\r\nis\r\na\r\nstring" = string:join(Words, "\r\n").
BinAgain = <<"this\r\nis\r\na\r\nstring">> = list_to_binary(Rejoined).
For your reference, the string module always expects a flat list (e.g., "this is a string", but not ["this", "is", "a", "string"]), except for string:join, which takes a list of flat strings.

Related

How to find a word in a single long string?

I want to be able to copy and paste a large string of words from say a text document where there are spaces, returns and not commas between each and every word. Then i want to be able to take out each word individually and put them in a table for example...
input:
please i need help
output:
{1, "please"},
{2, "i"},
{3, "need"},
{4, "help"}
(i will have the table already made with the second column set to like " ")
havent tried anything yet as nothing has come to mind and all i could think of was using gsub to turn spaces into commas and find a solution from there but again i dont think that would work out so well.
Your delimiters are spaces ( ), commas (,) and newlines (\n, sometimes \r\n or \r, the latter very rarely). You now want to find words delimited by these delimiters. A word is a sequence of one or more non-delimiter characters. This trivially translates to a Lua pattern which can be fed into gmatch. Paired with a loop & inserting the matches in a table you get the following:
local words = {}
for word in input:gmatch"[^ ,\r\n]+" do
table.insert(words, word)
end
if you know that your words are gonna be in your locale-specific character set (usually ASCII or extended ASCII), you can use Lua's %w character class for matching sequences of alphanumeric characters:
local words = {}
for word in input:gmatch"%w+" do
table.insert(words, word)
end
Note: The resulting table will be in "list" form:
{
[1] = "first",
[2] = "second",
[3] = "third",
}
(for which {"first", "second", "third"} would be shorthand)
I don't see any good reasons for the table format you have described, but it can be trivially created by inserting tables instead of strings into the list.

How to remove ANSI codes from a string?

I am working on string manipulation using LUA and having trouble with the following problem.
Using this as an example of the original data I am given -
"[0;1;36m(Web): You say, "Text here."[0;37m"
I want to keep the string intact except for removing the ANSI codes.
I have been pointed toward using gsub with the LUA pattern matching but I cannot seem to get the pattern correct. I am also unsure how to reference exactly the escape character sent.
text:gsub("[\27\[([\d\;]+)m]", "")
or
text:gsub("%x%[[%d+;+]m", "")
If successful, all I want to be left with, using the above example, would be:
(Web): You say, "Text here."
Your string example is missing the escape character, ASCII 27.
Here's one way:
s = '\x1b[0;1;36m(Web): You say, "Text here."\x1b[0;37m'
s = s:gsub('\x1b%[%d+;%d+;%d+;%d+;%d+m','')
:gsub('\x1b%[%d+;%d+;%d+;%d+m','')
:gsub('\x1b%[%d+;%d+;%d+m','')
:gsub('\x1b%[%d+;%d+m','')
:gsub('\x1b%[%d+m','')
print(s)

Converting type string to long

I am trying to convert the type of string to long in the following code:
PaymentReceived = String.Format(new CultureInfo("en-IN", true), "{0:n}", t.PaymentReceived),
Here t.PaymentReceived is of type long, and the PaymentReceived is of type string but I want it to be of type long.
I am using this to convert the PaymentReceived value into comma separated value.
I am trying to do as of my knowledge like
PaymentReceived = Convert.ToInt64( String.Format(new CultureInfo("en-IN", true), "{0:n}", t.PaymentReceived))
But the error is Additional information: Input string was not in a correct format.
So please help me with another solution, thank you.
The formatter n, adds additional non-numeric characters. For en-IN culture, that means a number like 1000 ends up as 1,000.00.
The Convert.ToInt64 method requires that the string be 100% numeric, including no period, which might be fine for Convert.ToDecimal, but a long is not a float. Therefore, emphatically, your string is not formatted correctly, and the error is both obvious and correct. I'm not sure what your ultimate goal here is, but it makes no sense to convert a long to a formatted string and then immediately convert it back to a long, anyways.
Assuming you have only the string and you need to format it as a long, then you need to ensure that it's formatted as a long should be. That requires:
Split on the decimal point and take just the left side:
str = str.Split(new[] { '.' })[0];
Replace any commas with empty strings:
str = str.Replace(",", "");
That assumes you know the format will something like 1,000.00. Otherwise, you may want to use a regex to replace all non-numeric characters with an empty string, instead. However, you still need to split on the decimal. Otherwise, if you just removed all non-numeric characters from something like 1,000.00, then you'd end up with 100000, a number 100 times larger than the actual string number. Also, this is all dependent on the culture. Some cultures use , as the decimal separator and . and delimiter in large numbers. If you need to handle various cultures, you'll need to adjust accordingly.

Lua How to replace 1 specific character inside table without whole string?

Already know how to show specific character.
table {"abc"}
return string.sub(table[1], 2, 2)
b
But want to replace 1 specific character inside the table without changing whole string.
table = {"abc"}
to
table = {"axc"}
In Lua, strings are strictly immutable, so they cannot be changed, per se.
As such, the only way to accomplish this is to create a new string with the content you want and insert it in table[1]. Whether or not the string is inside a table does not matter.
This would be accomplished, for example, by taking the beginning and end of the string and concatenating them with the new part:
local index = 2 -- The character we want to change
table[1] = string.sub(table[1], 1, index - 1) .. "x" .. string.sub(table[1], index + 1, -1)
This would extract all characters from the beginning of the string until the character before the one we wish to "replace", append the new character, then append the rest of the old string not including the character we "replaced".
In most cases, however, it is not very well-advised to play with single characters like this, as Lua has reasonably powerful pattern-matching and replacement facilities such as string.gsub, which allows you to replace even more complex substrings with ease. (Usage example from Programming in Lua available here)

Haskell -> After parsing how to work with strings

Hello
after doing the parsing with a script in Haskell I got a file with the 'appearance' of lists of strings. However when I call the file content with the function getContents or hGetContents, ie, reading the contents I get something like: String with lines (schematically what I want is: "[" aaa "," bbb "" ccc "]" -> ["aaa", "bbb" "ccc"]). I have tried with the read function but without results. I need to work with these lists of strings to concatenating them all in a single list.
I'm using the lines function, but I think it only 'works' one line at a time, doesn't it?
What I need is a function that verify if an element of a line is repeted on other line. If I could have a list of a list of strings it could be easier (but what I have is a line of a string that looks like a list of strings)
Regards
Thanks.
I have tried with the read function but without results
Just tested, and it works fine:
Prelude> read "[\"aaa\",\"bbb\",\"ccc\"]" :: [String]
["aaa","bbb","ccc"]
Note that you need to give the return type explicitly, since it can't be determined from the type of the argument.
I think the function you are looking for is the lines function from Data.List (reexported by the Prelude) that breaks up a multi-line string into a list of strings.
in my understanding, what you can do is
create a function that receives a list of lists, each list is a line of the entire string, of the argument passed in, and checks if a element of a line occurs in other line.
then, this function passes the entire string, separated by lines using [lines][1].

Resources