How can this be reversed in groovy?
ie.
I want to turn this:
[ [a:"c", b:"e"], [a:"d",b:"f"] ] -- can have more elements in the list
into: [a: ["c","d"], b: ["e","f"]]
So, we can:
Melt the list of maps into a long list where each element has a common k/v structure
Then group by the key
Then we need to go through this new map, and clean up the values
That gets us:
def result = [ [a:"c", b:"e"], [a:"d",b:"f"] ]
*.collect { [k: it.key, v: it.value] }
.flatten()
.groupBy { it.k }
.collectEntries { a, b ->
[a, b.v]
}
assert result == [a:['c', 'd'], b:['e', 'f']]
Related
I have a list of two-item lists:
def list = [[key1, value1], [key1, value1], [key2, value1], [key2, value2], ...]
I am trying to write Groovy code which will take "list" and return another list, which displays not only the frequency of each duplicate, two-item list, but also if there are items which are unique:
def newList = [[key1, value1:2], [key2, [value1:1, value2:1]], ...];
The reasoning behind this format is because I'd write more code to throw an error if a specific "key" had more than one "value". If there is an easier way to do this, any help/suggestions would be appreciated.
It normally helps if you show what you've tried when asking a question here...
In this case though, you just need:
def result = list.groupBy { it[0] }
.collect { k, v -> [k, v.countBy { it[1] }] }
And result will equal:
[['key1', ['value1':2]], ['key2', ['value1':1, 'value2':1]]]
You could also do something like this:
def result = list.groupBy { it[0] }
.collectEntries { k, v -> [k, v*.getAt(1).unique().size() ] }
To give you:
['key1':1, 'key2':2]
I have a list of values that looks something like this:
["Some", "random", "values", [], "in", "a", [], "list"].
I would like to create a new list with the empty list items removed. Like this:
["Some", "random", "values", "in", "a", "list"].
What is the easiest way of going about this? I assume using list comprehensions to build a new list is going to be the most efficient way of doing this. How would I filter this list using list comprehensions?
List comprehensions are a neater lists:filter/2:
[E || E <- List, E /= []]
This can be achieved using lists:filter.
List = ["Some", "random", "values", [], "in", "a", [], "list"],
lists:filter(fun(X) -> X /= [] end, List).
lists:filter takes a fun and a list. The fun should take a list item and return true or false. If the fun returns true the item is returned in the new list.
More information can be found here: http://erlangcentral.org/wiki/index.php?title=Filtering_Lists
Let's say that I have a Map of strings -> List of Integers. I would like to create a function which takes in as a parameter a List of strings and returns all the integers correlating to all the string in that list. I.e. if the Map X contains the following mappings:
database = [("Bob",[1,2,3]),("John",[1,5,6]),("Trevor",[4,5,7])]
If this function takes in ["Bob","John"] as the list of names, it should return,
[1,2,3,5,6]
Since Bob correlates to 1,2,3 and John correlates to 1,5,6 (same entries for both names aren't duplicated). I also would like to not introduce a mutable variable if I don't have to, thus leading me to believe a for comprehension that yields this list of number values would be the best way to achieve this, but I'm not sure how.
If you want to use a for-comprehension you can so this:
val result = for {
key <- keys
nums <- map.get(key).toSeq
num <- nums
} yield num
result.distinct
Explanation:
for each key in the list try to get an entry and convert it to a Seq (necessary because flatMap expects a Seq in this case) and add every number in the list to the result. If the key is not present in the map the collection will be empty and therefore not yield any results. At the end call distinct to remove the duplicates.
val myMap = Map("Bob" -> List(1,2,3), "John" -> List(1,5,6), "Trevor" -> List(4,5,7))
val names = List("Bob", "John")
You can add default value to Map using method withDefaultValue:
val mapWithDefaul = myMap withDefaultValue Nil
Then you could use Map as function in flatMap:
names.flatMap(mapWithDefaul).distinct
// List(1, 2, 3, 5, 6)
Let
val db = Map("Bob" -> List(1,2,3), "John" -> List(1,5,6), "Trevor" -> List(4,5,7))
val names = List("Bob", "John")
Then a similar approach to #senia's using flatMap,
implicit class mapCorr[A,B](val db: Map[A,List[B]]) extends AnyVal {
def corr(keys: List[A]): List[B] = {
keys.flatMap{ k => db get k }.flatten.distinct
}
}
and
scala> db.corr(keys)
res0: List[Int] = List(1, 2, 3, 5, 6)
Here we allow for key lists of type A and maps from type A to type List[B] .
val myset = Set("Bob","John")
val database = Map(("Bob"->List(1,2,3)),("John"->List(1,5,6)),("Trevor"->List(4,5,7)))
val ids = database.filter(m => myset.contains(m._1)).map(_._2).flatten.toList.distinct
outputs:
ids: List[Int] = List(1, 2, 3, 5, 6)
Something like:
val result = database.filter(elem => list.contains(elem._1)).foldLeft(List())((res,elem) => res ++ elem._2)
where list is the input list of names.
I have i list:
[["asd", "ddsa"], ["ASD", "ASD"], ["FH", "SDFDF]].
How can i applicate function F to each element of this list? How can i map this list?
Thank you.
If assuming by element you mean "asd", your main List will always be two levels deep as in your example and your returned result shall be in the same format, this will due.
List1 = [["asd", "ddsa"], ["ASD", "ASD"], ["FH", "SDFDF]]
[ [ F(String) || String <- List2 ] || List2 <- List1 ]
If you mean that your element is ["asd","ddsa"] just use lists:map/2 or list comprehension as below.
List1 = [["asd", "ddsa"], ["ASD", "ASD"], ["FH", "SDFDF]]
[ F(List2) || List2 <- List1 ]
You could define a deepMap function, performing something like:
deepMap(Fun, T) ->
case is_list(T) of
true -> lists:map(fun(E) -> deepMap(Fun,E) end, T);
false -> Fun(T)
end.
If the input is not a list, evaluate your function. If it is a list, apply deepMap to all elements using map, using your function.
I am trying to do basic list operations with SML.
I want to extract each element of the list and append string to that element and add it back to the list.
Example:
List : [A,B,C,D]
String : A
Final List: [AA,AB,AC,AD]
How can I iterate through each element in the list in SML? I can append strings using ^ and concatenate lists using # but how do I extract each element from the list?
Also can we use something like map or arrays to store these list values and pass it to different functions in SML?
I could just find some vague information about map and no definite information as to how we can use it.
two easy ways to do this:
- fun addstring (x::xs) a = (a^x) :: addstring xs a
= | addstring [] a = []
= ;
val addstring = fn : string list -> string -> string list
- addstring ["A", "B", "C", "D"] "A";
val it = ["AA","AB","AC","AD"] : string list
The above uses pattern matching to destruct the list, performs the operation, then constructs the list again, recursing as it goes.
- fun addstring2 xs a = map (fn x => a^x) xs;
val addstring2 = fn : string list -> string -> string list
- addstring2 ["A", "B", "C", "D"] "A";
val it = ["AA","AB","AC","AD"] : string list
This one is a fair bit simpler (if perhaps a tiny bit harder to read than the explicit cases in addstring.) but it shows how map is used - you specify a function that maps each element from the source to the target domain, give it a list of elements in the source domain, and it returns a list in the target domain.
of course, neither of these do in-place updating of the list, they return the new list.