Reputation: 433
there is a List as below:
val a: List[String] = List(aaaaa1, aaaaa2, bb, cc, dd1, ee, dd2, dd3, ff, ggg1, ggg2, aaaaa3)
how to delete the elements that have the same prefix String (2 to 5 Chars) in a List?
for example:
"aaaaa1","aaaaa2","aaaaa3" have the same prefix String "aaaaa"(5 Chars). so delete them.
"dd1","dd2","dd3" have the same prefix String "dd"(2 Chars). so delete them.
"ggg1","ggg2" have the same prefix String "ggg"(3 Chars). so delete them.
expected:
val b: List[String] = List(bb,cc,ee,ff)
==========
thx for your idea. now fix it.
a.foldLeft(scala.collection.mutable.LinkedHashMap[String,Int]().withDefaultValue(0)){
case(m,e) =>
val k = e.take(2)
m(k)+=1
m
}.filter(_._2==1).keys.toList
Upvotes: 2
Views: 127
Reputation: 51271
Try this.
a.groupBy(_.take(2)).values.collect{case x if x.length == 1 => x.head}
// res0: Iterable[String] = List(cc, bb, ee, ff)
The original order is not retained because the collection passes through a Map()
phase which, by definition, has no intrinsic order.
update
The original order can be preserved but it requires a two-step procedure.
val uniqPrefix = a.groupBy(_.take(2)).mapValues(_.length == 1)
a.filter(x => uniqPrefix(x.take(2)))
// res0: List[String] = List(bb, cc, ee, ff)
Upvotes: 2
Reputation: 3068
I think this code can be used in this case:
val list = List(
"aaaaa1", "aaaaa2", "bb", "cc", "dd1", "ee", "dd2", "dd3", "ff", "ggg1", "ggg2", "aaaaa3")
val prefix2items = list.groupBy(_.take(2))
list.filter(item => prefix2items(item.take(2)).length == 1)
//res0: List[String] = List(bb, cc, ee, ff)
Upvotes: 1
Reputation: 413
This would work even if you have multiple character in prefix
The prefix will be identify until get a digit, the character after digit will not consider as prefix here
val a = List("abb1","abbbbbb1","aaaaa2","aaaaa3","aaaaaa44")
"abb1" will be removed here
a.filter(_.takeWhile(data => !data.isDigit).groupBy(_.toChar).values.exists{case x if (2 to 5).contains(x.length) => true case _ => false})
Upvotes: 0