Reputation: 8958
I'm trying to add every element of a list to a MutableSet.
Thrift:
Obj {
list<Tag> myList;
}
enum Tag {
...
}
Scala:
val uniqueTags = Set[Tag]()
// obj is of type Obj defined in the thrift above
obj.flatMap(_.myList).foreach(uniqueTags += _)
However the compiler says that I'm trying to add Seq[Tag]
instead of Tag
. How to get to the element represented by Seq?
Also I'm sure there is another way to initialize the Set with the list directly. I tried obj.flatMap(_.myList).toSet()
and Set[Tag](obj.flatMap(_.myList))
) but none worked.
Upvotes: 1
Views: 1382
Reputation: 31232
you don't need to iterate to find unique, scala does that for you with toSet
Example using toSet
:
scala> case class Obj(myList: List[String])
defined class Obj
scala> val obj = Option(Obj(myList = List("metal", "rock", "prog", "pop", "pop")))
obj: Option[Obj] = Some(Obj(List(metal, rock, prog, pop, pop)))
Now, to get unique tags,
scala> val uniqueTags = obj.map(_.myList).getOrElse(List.empty[String]).toSet
uniqueTags: scala.collection.immutable.Set[String] = Set(metal, rock, prog, pop)
foreach
are not recommended to mutate stuffs in fp world. The other approach would be to use accumulator pattern - foldLeft
,
scala> import scala.collection.immutable.Set
import scala.collection.immutable.Set
scala> obj.map(_.myList).getOrElse(List.empty[String]).foldLeft(Set[String]()){ case (s, e) => s + e }
res15: scala.collection.immutable.Set[String] = Set(metal, rock, prog, pop)
The mutable approach is to use forach
as you are doing, (not recommended)
scala> val uniqueTags = scala.collection.mutable.Set[String]()
uniqueTags: scala.collection.mutable.Set[String] = HashSet()
scala> obj.map(_.myList).getOrElse(List.empty[String]).foreach { elem => uniqueTags += elem }
scala> uniqueTags
res13: scala.collection.mutable.Set[String] = HashSet(metal, rock, pop, prog)
Upvotes: 3
Reputation: 455
I an not sure what is Obj. But in you case: obj.flatMap(_.myList)
will give a list of Tag. I think the correct way is:
obj.flatMap(_.myList).foreach(uniqueTags += _)
I think you can use mutable in Scala. Its not a big deal. According to your obj, you may use different way to append the element into set
case class Obj(myList: List[String])
val obj = Obj(List("1", "2", "3"))
// first example when your obj is a single Obj
val uniqueTags = mutable.Set[String]()
// obj is of type Obj defined in the thrift above
obj.myList.foreach(uniqueTags += _)
printf(uniqueTags.toString()) // give you Set(1, 2, 3)
// second example when your obj is a list of Obj
val obj2 = List(obj, obj, obj)
val uniqueTags2 = mutable.Set[String]()
obj2.flatMap(_.myList).foreach(uniqueTags2 += _)
printf(uniqueTags2.toString()) // give you Set(1, 2, 3) also
Upvotes: 0