I am looking for efficient solution to remove empty string in a list in Julia.
Here is my list :
li = ["one", "two", "three", " ", "four", "five"]
I can remove empty string by using for loop, as following :
new_li = []
for i in li
if i == " "
else
push!(new_li, i)
end
end
But I believe there is more efficient way to remove the empty string.
new_li = filter((i) -> i != " ", li)
or
new_li = [i for i in li if i != " "]
I have a couple of comments a bit too long for the comments field:
Firstly, when building an array, never start it like this:
new_li = []
It creates a Vector{Any}, which can harm performance. If you want to initialize a vector of strings, it is better to write
new_li = String[]
Secondly, " " is not an empty string! Look here:
jl> isempty(" ")
false
It is a non-empty string that contains a space. An empty string would be "", no space. If you're actually trying to remove empty strings you could do
filter(!isempty, li)
or, for in-place operation, you can use filter!:
filter!(!isempty, li)
But you're not actually removing empty strings, but strings consisting of one (or more?) spaces, and maybe also actually empty strings? In that case you could use isspace along with all. This will remove all strings that are only spaces, including empty strings:
jl> li = ["one", "", "two", "three", " ", "four", " ", "five"];
jl> filter(s->!all(isspace, s), li)
5-element Vector{String}:
"one"
"two"
"three"
"four"
"five"
Related
I would love to take an array of strings
let array = ["one", "two", "three", "four"]
and convert it to the regex builder equivalent of:
Regex {
ChoiceOf{
"one"
"two"
"three"
"four"
}
}
or basically the equivelant of:
/one|two|three|four/
so far I have tried:
let joinedArray = array.joined(separator: "|")
let choicePattern = Regex(joinedArray)
I know that using Regex() throws and I need to handle that somehow but even when I do, I don't seem to get it to work.
Does anyone know how to do this?
I have two list of Strings. Now I want to replace every occurence of a word in the first list at index i with a word in the second list at index i of a sentence.
So if I have
list a=("am","I","my")
and
list b=("are","You","your")
I want the sentence "I am an amateur"
to become "You are an amateur"
What is cleanest way to do that in Kotlin (without for loop)?
First split the string to a list of its words and then map each word if it exists in list a to the corresponding word in list b. Finally rejoin the string:
val a= listOf("am","I","my")
val b= listOf("are","You","your")
val str = "I am an amateur"
val new = str
.split("\\s+".toRegex())
.map { val i = a.indexOf(it); if (i < 0) it else b[i] }
.joinToString(" ")
Another way of doing the same thing is:
var new = " $str "
a.forEachIndexed { i, s -> new = new.replace(" $s ", " ${b[i]} ") }
new = new.trim()
although this is closer to a for loop.
I assume there is no punctuation, all whitespaces are spaces and so on.
val m = a.zip(b).toMap()
return s.split(' ').joinToString(" ") { m[it] ?: it }
First you create a map m for more efficient... mapping. Then
Split the string to get a list of words
Map all words: if m contains the word, then return the value (i.e. the replacement), otherwise return the original word (since we shouldn't replace it).
Join all words, separate them by spaces.
You can use the regular expression \b\w+\b to match words in a sentence and then call replace function with the lambda that provides a replacement string for each match:
val input = "I am an amateur, alas."
val wordsToReplace = listOf("I", "am", "my")
val wordsReplaceWith = listOf("You", "are", "your")
val wordRegex = """\b\w+\b""".toRegex()
val result = wordRegex.replace(input) { match ->
val wordIndex = wordsToReplace.indexOf(match.value)
if (wordIndex >= 0) wordsReplaceWith[wordIndex] else match.value
}
println(result)
If there are a lot of word in your lists, it makes sense to build a map of them to speed up searches:
val replaceMap = (wordsToReplace zip wordsReplaceWith).toMap()
val result = wordRegex.replace(input) { match ->
replaceMap[match.value] ?: match.value
}
I think the simplest way is to create a set of regex you want and replace the string by iteration. Let's say you want to replace the word "am", your regex will be "\bam\b". You can use "(?i)\bam\b" if you want it not to be case sensitive. To make "I am an amateur" to "You are an amateur"
val replacements = setOf("\\bam\\b" to "are",
"\\bI\\b" to "You",
"\\bmy\\b" to "your")
replacements.forEach {
str = str.replace(Regex(it.first), it.second)
}
Given a std::vector of strings, what is the best way of removing all elements starting from the end that are empty (equal to empty string or whitespace). The removal of elements should stop when a non-empty element is found.
My current method, (work in progress) is something like:
while (Vec.size() > 0 && (Vec.back().size() == 0 || is_whitespace(Vec.back()))
{
Vec.pop_back();
}
where is_whitespace returns a bool stating if a string is whitespace or not
I suspect that my method will resize the vector at each iteration and that is suboptimal. Maybe with some algorithm it is possible to do in one step.
Input: { "A", "B", " ", "D", "E", " ", "", " " }
Desired Output: { "A", "B", " ", "D", "E" }
As I did not find a good dupe on first glance, here is a simple solution:
// Helper function to see if string is all whitespace
// Can also be implemented as free-function for readablity and
// reusability of course
auto stringIsWhitespace = [](const auto &str)
{
return std::all_of(
begin(str), end(str), [](unsigned char c) { return std::isspace(c); });
};
// Find first non-whitespace string from the back
auto it = std::find_if_not(rbegin(Vec), rend(Vec), stringIsWhitespace);
// Erase from there to the end
Vec.erase(it.base(), end(Vec));
Note the unsigned in the lambda due to this gotcha.
Live example thanks to #Killzone Kid.
Here's a better way:
for (auto it = Vec.rbegin(); it != Vec.rend() && is_whitespace(*it); )
{
it = Vec.erase(it);
}
It will start from the end and stop once non-whitespace has been encountered or the beginning of the vector is reached, whichever comes first. Note that I don't increment the iterator in the for loop.
How do I convert a list of strings into a string in DrRacket? For example, if I have
'("44" "444") convert it into "44 444"?
I tried string-join, but it takes a delimiter and if I put one it replaces the space with the delimiter and if I use "" for the delimiter it simply gets rid of it.
In fact string-join is the right procedure for using in this case, simply use " " (a single space) as delimiter:
(string-join '("44" "444") " ")
=> "44 444"
Just to clarify: in a list the spaces between elements are not considered part of the list, they're there to separate the elements. For example, all these lists are equal and evaluate to the same value:
'("44""444")
'("44" "444")
'("44" "444")
If for some reason you want to consider the spaces as part of the list then you have to explicitly add them as elements in the list:
(define lst '("a" " " "b" " " "c" " " "d"))
(string-join lst "")
=> "a b c d"
hey i was wandering if it was possible to show a list:
["one", "two", "three"]
to be shown as
"one", "two", "three"
need it done for a file
thanks
You can do this with intercalate from Data.List
showList :: Show a => [a] -> String
showList = intercalate ", " . map show
The map show converts each element to it's string representation with quotes (and any internal quotes properly escaped), while intercalate ", " inserts commas and spaces between the pieces and glues them together.