Assign splited string to array in elixir - string

I am new in elixir development. I have problem with parsing of string in elixir. Assume that I have string "Hello World from the hell". I know that I can split this like this String.split("Hello World from the hell"). I would like to know is the anyway to assign element of this string to list in elixir?

String.split/1 returns a list - one of Elixir's fundamental data structures, along with maps and tuples. A list is your go-to basic collection in Elixir. Even though internally it's a linked list, you can perform all sorts of operations on it using functions from the Enum module:
$ iex
iex(1)> ls = String.split("Hello World from the hell")
["Hello", "World", "from", "the", "hell"]
iex(2)> i ls
Term
["Hello", "World", "from", "the", "hell"]
Data type
List
Reference modules
List
iex(3)> Enum.take(ls, 2)
["Hello", "World"]
iex(4)> Enum.at(ls, 4)
"hell"
iex(5)> [l0, l1, l2, l3, l4] = ls
["Hello", "World", "from", "the", "hell"]
iex(6)> l4
"hell"
iex(7)> Enum.take(ls, 4) ++ ["iex", "shell"]
["Hello", "World", "from", "the", "iex", "shell"]
As you can see Enum.at/3 gives you something similar to the a[i] style array access.
If you're worried about the efficiency of finding an element in your list - for example your input string is going to be something much longer than "Hello World from the hell" and you'll be getting elements from it by index many times, essentially traversing it each time, you can build a map from it instead, and look the words by indices efficiently:
iex(8)> with_indices = Enum.with_index(ls)
[{"Hello", 0}, {"World", 1}, {"from", 2}, {"the", 3}, {"hell", 4}]
iex(9)> indices_and_words = Enum.map(with_indices, fn({a, b}) -> {b, a} end)
[{0, "Hello"}, {1, "World"}, {2, "from"}, {3, "the"}, {4, "hell"}]
iex(10)> map = Map.new(indices_and_words)
%{0 => "Hello", 1 => "World", 2 => "from", 3 => "the", 4 => "hell"}
iex(11)> map[0]
"Hello"
iex(12)> map[4]
"hell"

Related

Prolog: Konvert List into Strings seperated by "-sign

I'm looking for some SWI-Prolog predicate which is able to convert some list A=[X1, X2,..., Xn] into some string of following form, based on some key K:
'"K": ["X1", "X2", ..., "Xn"]'
My idea to solve this problem gives the following predicate:
list_to_keylist(List, Key, KeyList) :-
findall(X, (member(Y, List), term_to_atom(Y, X)), ListStrings),
term_to_atom(ListStrings, StringList),
format(atom(KeyList), '"~w": ~w', [Key, StringList]).
unfortunately the call:
list_to_keylist([1,2],0,K).
gives the output:
K = '"0": [\'1\',\'2\']'
is there a possibility to replace \' by "?

Concat a sublist of strings intro string elements of a list

Say I have a list of substrings [["hello", "how", "are", "you?"], ["I'm", "doing", "great"]] and I wanted to create a list of ["hello how are you?", "I'm doing great"] how would one go about this?
I've tried
sum(mylist, [])
>> ["hello", "how", "are", "you?", "I'm", "doing", "great"]
and also
new_list = []
for i in mylist:
new_list += i
>> ["hello", "how", "are", "you?", "I'm", "doing", "great"]
And neither seem to what I want it to do. I suspect that I need to join the subarrays first, and then append them maybe to a new list. Any thoughts or suggestions?
Once more the goal is to take:
[["hello", "how", "are", "you?"], ["I'm", "doing", "great"]]
and make it into:
["hello how are you?", "I'm doing great"]
One simple way to do it is use list comprehension:
nested_lists = [["hello", "how", "are", "you?"], ["I'm", "doing", "great"]]
joined_list = [' '.join(str_list) for str_list in nested_lists]
print(joined_list)
# Outputs ['hello how are you?', "I'm doing great"]
essentially list comprehension merges a loop and list construction in the same construct - see line 2.
my_list = [["hello", "how", "are", "you?"], ["I'm", "doing", "great"]]
new_list = []
for mini_list in my_list:
new_list.append(' '.join(mini_list)
This would therefore, take each item from that list which itself is a list and join them.
It will then append it to what I'm calling the new_list to give you the result you want.
Just mapping all sublists with ' '.join:
new_list = [*map(' '.join, mylist)]
Or one character shorter:
*new_list, = map(' '.join, mylist)

Find the elements between matching elements in two lists

Let's say I have two lists of words called query and sentence. What I want to find is, for each pair of consecutive words in the query, a list of all the words between those two in the sentence. Also, if the first word of the query is not the first word of the sentence, the result should include a list with all the words in the sentence up to that one (and the same goes for the last word in the query).
So for example, if the query and the sentence looked like this:
query = ["like", "with"]
sentence = ["I", "like", "coffee", "with", "sugar", "and", "milk"]
then the result should be:
result = [["I"], ["coffee"],["sugar", "and", "milk"]]
However, there might be more than one way to make this match, depending on the sentence and query. For example:
query = ["bear", "my"]
sentence = ["I", "cannot", "bear", "when", "my", "bear", "leaves", "my", "house"]
In this case, there are many valid results:
result1 = [["I", "cannot"], ["when"], ["bear", "leaves", "my", "house"]]
result2 = [["I", "cannot"], ["when", "my", "bear", "leaves"], ["house"]]
result3 = [["I", "cannot", "bear", "when", "my"], ["leaves"], ["house"]]
So, what I need is a list of all the possible results for a given sentence and query. I've been trying to come up with a solution for a while now, but I can't work out how to find all possible combinations without making a mess of my code.
This is an exercise in non-determinism, which is modeled by the [] monad.
Start by writing a function
foo :: String -> [String] -> [([String], [String])]
that can split sentence into exactly two parts based on a given word. That is,
foo "bear" sentence == [
(["I", "cannot"], ["when", "my", "bear", "leaves", "my", "house"]),
(["I", "cannot", "bear", "when", "my"], ["leaves", "my", "house"]),
]
Given a list of split words, you recursively split the second list using the next split word.
do_it [] _ = []
do_it (q:qs) words = do
(x, y) <- foo q words
return (x : do_it qs words)

Groovy way to merge two lists of maps with some calculations

I need to merge to maps while perform some calculation for example having the following maps that always will be the same size
def map1 = [
[name: 'Coord1', quota: 200],
[name: 'Coord2', quota: 300]
]
def map2 = [
[name: 'Coord1', copiesToDate: 270],
[name: 'Coord2', copiesToDate: 30]
]
I want to get this map
def map3 = [
[name: 'Coord1', quota: 200, copiesToDate: 60, balance: 140],
[name: 'Coord2', quota: 300, copiesToDate: 30, balance: 270]
]
Right now i am trying with this solution and its working
def map4 = map1.collect { m1 ->
[
name: m1.name,
quota: m1.quota,
copiesToDate: map2.find { m2 ->
m1.name == m2.name
}.copiesToDate,
balanceToDate: m1.quota - map2.find { m2 ->
m1.name == m2.name
}.copiesToDate
]}
Could you please share a groovy way to do this task. Thanks
Grooviest code I could come up with:
def map3 = [map1, map2].transpose()*.sum().each { m ->
m.balance = m.quota - m.copiesToDate
}
edit: as noted by Tim, this code works as long as the two input lists (map1 and map2) are of the same size and have the maps in order. If this is not the case I would recommend Tim's answer which handles those cases.
The above returns the map as defined in your question. The following code:
def list1 = [
[name: 'Coord1', quota: 200],
[name: 'Coord2', quota: 300]
]
def list2 = [
[name: 'Coord1', copiesToDate: 60],
[name: 'Coord2', copiesToDate: 30]
]
def x = [list1, list2].transpose()*.sum().each { m ->
m.balance = m.quota - m.copiesToDate
}
x.each {
println it
}
demonstrates the idea and prints:
[name:Coord1, quota:200, copiesToDate:60, balance:140]
[name:Coord2, quota:300, copiesToDate:30, balance:270]
I have renamed map1 and map2 into list1 and list2 since they are in fact two lists containing inner maps.
The code is somewhat concise and might need a bit of explanation if you're not used to transpose and the groovy spread and map operations.
Explanation:
[list1, list2] - first we create a new list where the two existing lists are elements. So we now have a list of lists where the elements in the inner lists are maps.
.transpose() - we then call transpose which might need a bit of effort to grasp when you see it for the first time. If you have a list of lists, you can see transpose as flipping the lists "into the other direction".
In our case the two lists:
[[name:Coord1, quota:200], [name:Coord2, quota:300]]
[[name:Coord1, copiesToDate:60], [name:Coord2, copiesToDate:30]]
become:
[[name:Coord1, quota:200], [name:Coord1, copiesToDate:60]]
[[name:Coord2, quota:300], [name:Coord2, copiesToDate:30]]
i.e. after transpose, everything relating to Coord1 is in the first list and everything relating to Coord2 is in the second.
Each of the lists we have now is a list of Maps. But what we want is just one map for Coord1 and one map for Coord2. So for each of the above lists, we now need to coalesce or merge the contained maps into one map. We do this using the fact that in groovy map+map returns a merged map. Using the groovy spread operator *. we therefore call sum() on each list of maps.
i.e.:
[[name:Coord1, quota:200], [name:Coord1, copiesToDate:60]].sum()
computes into:
[name:Coord1, quota:200, copiesToDate:60]
and:
[[name:Coord2, quota:300], [name:Coord2, copiesToDate:30]].sum()
into:
[name:Coord2, quota:300, copiesToDate:30]
lastly we want to add the balance property to the maps so we iterate through what is now a list of two maps and add balance as a computation of quota - copiesToDate. The each construct returns the list it is working on which is what we assign to x.
Don't call find twice. Use the Map.plus() method to append new entries. Handle missing names from map2.
def map3 = map1.collect {m1 ->
def m2 = map2.find {it.name == m1.name} ?: [copiesToDate: 0]
m1 + m2 + [balance: m1.quota - m2.copiesToDate]
}
Another option for fun :-)
def result = (map1 + map2).groupBy { it.name }
.values()
*.sum()
.collect { it << ['balance': it.quota - it.copiesToDate] }
add the lists together
group by the name
get the grouped values and concatenate them
then for each of them, work out the balance

Vector comprehension in R - paste function

Is there a way in R to write vector comprehension using the paste function?
I simply need to get a one string representation of a (long) vector (data), like this:
data = [1, 58, 120]
s = paste(data[1], data[2], data[3], sep=", ")
Isn't there a nicer solution than do this in a for-loop?
I found this about comprehensions in R:
List comprehension in R
but it does not seem to work with paste.
Like #dickoa already commented, reducing a vector s into one string separated by , you can use paste:
data <- c(1, 2, 3)
paste(data, collapse = ", ")

Resources