How to collate list items with the same first item onto a map - list

I know this is probably a very simple List operation in Scala, but I'm a newbie and can't figure it out. I have a query that returns a result set with a series of values, grouped by a common id. For example:
Result Set:
[{ 1, "a", 30 },
{ 1, "b", 20 },
{ 1, "c", 22 },
{ 2, "a", 32 },
{ 2, "c", 10 }]
and what I'd like to do is put this into a map as such:
1 -> [{"a", 30}, {"b", 20}, {"c", 22}]
2 -> [{"a", 32}, {"c", 10}]
I think the collect method can be used for this but can't figure it out.

I'm not sure what the types in your data structure are, but maybe you can adapt this. This assumes you have a collection of tuples:
val items =
List((1, "a", 30),
(1, "b", 20),
(1, "c", 22),
(2, "a", 32),
(2, "c", 10))
items
.groupBy{ case (a,b,c) => a }
.mapValues(_.map{ case (a,b,c) => (b,c) })
// Map(1 -> List((a,30), (b,20), (c,22)), 2 -> List((a,32), (c,10)))
Or, more succinctly:
items.groupBy(_._1).mapValues(_.map(t => (t._2, t._3)))
The collect method is something else entirely (basically, it's map that drops non-matching values). The groupBy method is what you were really looking for.

Related

Group list of tuples and sum the integers

I have the following list:
List(List(("hello", "goodbye", 12), ("hello", "goodbye", 15)), List(("hello", "test", 18), ("hello", "test", 20)), List(("something", "different", 30), ("something", "different", 18)))
I would like to get the following result:
List(("hello", "goodbye", 27), ("hello", "test", 38), ("something", "different", 48))
I've tried to use .map and .groupBy, but I can't seem to find a way to get it working.
This appears to get what you're after as long as the order of result elements is unimportant.
val data =
List(List(("hello", "goodbye", 12), ("hello", "goodbye", 15)), List(("hello", "test", 18), ("hello", "test", 20)), List(("something", "different", 30), ("something", "different", 18)))
data.flatten
.groupMapReduce(tup => (tup._1,tup._2))(_._3)(_+_)
.map{case ((k1,k2),v) => (k1,k2,v)}
.toList
//res0: List[(String, String, Int)] =
// List((hello,test,38), (something,different,48), (hello,goodbye,27))
Notice that I flatten away all the inner sub-Lists and focus only on the String elements in the tuples. It's not completely clear if that's what you intend.
You can:
Flatten those lists into a single list
Group by the first two elements of each list
Reduce on the third element of each list in each group
val list = List(
List(("hello", "goodbye", 12), ("hello", "goodbye", 15)),
List(("hello", "test", 18), ("hello", "test", 20)),
List(("something", "different", 30), ("something", "different", 18))
)
val result = list.flatten.groupBy { case (s1, s2, _) => (s1, s2) }.values.map(_.reduce((s1, s2) => (s1._1, s1._2, s1._3 + s2._3)))
// List((hello,test,38), (hello,goodbye,27), (something,different,48))
If inner list can have different "keys" - you can flatten your list of lists with flatMap(identity) or flatten then group the result using first two elements of the tuples and reduce the groupping with sum:
val collection = ...
collection
.flatten
.groupMapReduce(t => (t._1, t._2))(identity)((l,r) => (l._1, l._2, l._3+r._3))
.values
.toList

How to separate similar tuples based on some similar attribute?

I have a tuple list which looks like this:
val days= List(("Sunday", 1), ("Monday", 2), ("Tuesday", 1),
("Wednesday", 2), ("Thursday", 3), ("Friday", 2),
("Saturday", 3))
I want the final result to look like this:
"data": [
[
"Sunday, 1",
"Tuesday, 1"
],
[
"Monday, 2",
"Friday, 2"
"Wednesday,2"
],
[
"Thursday, 3",
"Saturday,3"
]
]
You can group and then map values:
days.groupBy(_._2)
.mapValues(_.map { case (name, nr) => s"$name, $nr" } )
.valuesIterator.toList
The result is:
List(List(Monday, 2, Wednesday, 2, Friday, 2), List(Sunday, 1, Tuesday, 1), List(Thursday, 3, Saturday, 3))
P.S.: As Luis Miguel Mejía Suárez suggests, using groupMap (from scala 2.13) can make this a bit more concise and readable:
days.groupMap(_._2) { case (name, nr) => s"$name, $nr" }
.valuesIterator.toList

How to get an index of a list element in elixir?

I have
>> list = ["a","b","c"]
and I need to get the index of the elements and create a new list that follows
>> list_2 = [[1,"a"], [2,"b"], [3,c]]
to create the new list I used
lista = Enum.flat_map(list, fn x -> [index,x] end)
but I can't find a function like to get the "index" value
list = ["a","b","c"]
list_2 = Enum.with_index(list)
gives
[{"a", 0}, {"b", 1}, {"c", 2}]
Enum.zip/2 is your friend here.
list = ~w[a b c]
#⇒ ["a", "b", "c"]
list_2 = Enum.zip(1..3, list)
#⇒ [{1, "a"}, {2, "b"}, {3, "c"}]
or, if the size is unknown upfront, you might
Enum.zip(Stream.iterate(1, & &1 + 1), list)
#⇒ [{1, "a"}, {2, "b"}, {3, "c"}]
to get a lists, not tuples, simply map the result
1
|> Stream.iterate(& &1+1)
|> Enum.zip(list)
|> Enum.map(&Tuple.to_list/1)
#⇒ [[1, "a"], [2, "b"], [3, "c"]]
Another way would be to use Enum.with_index/1
list
|> Enum.with_index(1)
|> Enum.map(fn {e, i} -> [i, e] end)
#⇒ [[1, "a"], [2, "b"], [3, "c"]]
I know the below answer is not related to asked question, but I'm sure it will help some in the feature.
In my case, I have to add an index to an array of lists/map.
So I did the below:
formatted_list = [%{"map 1": 1}, %{"map 2": 2}]
list_with_index = formatted_list
|> Enum.with_index(1)
|> Enum.map(fn {e, i} -> Map.put(e, :index, i) end)
Result:
[
{
"index": 1,
"map 1": 1
},
{
"index": 2,
"map 2": 2
}
]

Scala list take with offset

For example I have val source = List("1", "2", "3", "4", "5", "6", "7")
and I need get 3 elements start with second element. expected List("2","3") or List("3","4").
Is there any methods or any data structure with this ability?
I think slice is exactly what you're looking for
scala> val source = List("1", "2", "3", "4", "5", "6", "7")
source: List[String] = List(1, 2, 3, 4, 5, 6, 7)
scala> source.slice(2, 4)
res0: List[String] = List(3, 4)
Use combinations of drop and take methods:
source.drop(2).take(3) // List(3, 4, 5)
drop - skip first n elements
take - grab n elements
Getting three elements, starting with second,
source.tail.take(3)
which delivers
List(2, 3, 4)

How to count elements from list if specific key present in list using scala?

I have following list structure -
"disks" : [
{
"name" : "A",
"memberNo" :1
},
{
"name" : "B",
"memberNo" :2
},
{
"name" : "C",
"memberNo" :3
},
{
"name" : "D",
}
]
I have many elements in list and want to check for 'memberNo', if it exists
I want count of from list elements.
e.g. here count will be 3
How do I check if key exists and get count of elements from list using scala??
First create class to represent your input data
case class Disk (name : String, memberNo : String)
Next load data from repository (or other datasource)
val disks: List[Disk] = ...
And finally count
disks.count(d => Option(d.memberNo).isDefined)
In a similar fashion as in #SergeyLagutin answer, consider this case class
case class Disk (name: String, memberNo: Option[Int] = None)
where missing memberNo are defaulted with None; and this list,
val disks = List( Disk("A", Some(1)),
Disk("B", Some(2)),
Disk("C", Some(3)),
Disk("D"))
Then with flatMap we can filter out those disks with some memberNo, as follows,
disks.flatMap(_.memberNo)
res: List[Int] = List(1, 2, 3)
Namely, for the counting,
disks.flatMap(_.memberNo).size
res: Int = 3
Likewise, with a for comprehension,
for (d <- disks ; m <- d.memberNo) yield m
res: List[Int] = List(1, 2, 3)