0

We have a list of strings and i grouping them by below program. input: val k = List("a", "a", "a", "a", "b", "c", "c", "a", "a", "d", "e", "e", "e", "e")

output: *List(List(a, a, a, a), List(b), List(c, c), List(a, a), List(d), List(e, e, e, e))*

Program:

  def pack(ls:List[String]):List[List[String]]={

    val (a,next) = ls span {_ == ls.head}

    if ((next) == Nil) List(a)
    else a :: pack(next)

  }          

However when i do a List cons operators, i get the output as mentioned below.

Input:

val a =List("a", "a", "a", "a")        
val b = List ("b")                     
val c = List ("c", "c" )               
val a1 = List("a", "a")                
val d = List("d")                      
val e = List( "e", "e", "e", "e")      

*List(a::b::c::a1::d::e)*                

output:

*List(List(List(a, a, a, a), List(b), List(c, c), List(a, a), List(d), e, e, e, e))*

Is there any way i can the output as below in a single command in scala?

*List(List(a, a, a, a), List(b), List(c, c), List(a, a), List(d), List(e, e, e, e))* 
keerthi
  • 23
  • 1
  • 8
  • I think the question is about the cons operator and how to make it mimic the result of the "grouping" function - and not about how to implement the grouping itself, so not sure it's actually a duplicate. – Tzach Zohar Oct 27 '16 at 16:50
  • 1
    @TzachZohar yeah sorry, I was too quick in my judgment. Re-open – Gabriele Petronella Oct 27 '16 at 17:02

3 Answers3

1
scala> a::b::c::a1::d::List(e)
res0: List[List[String]] = List(List(a, a, a, a), List(b), List(c, c), List(a, a), List(d), List(e, e, e, e))

The cons operator prepends an item to a list - so construct a List around the last one if you want to then prepend all the other items one by one.

The easiest way to think about this is noticing the types:

  • To construct a List[List[String]], the cons operator expects to operate on an a List[String] on the left and a List[List[String]] on the right, to produce a new List[List[String]]: on the left should be an item in the resulting list, and on the right - a list with the same type as the expected result
  • When you write d::e, you're doing List[String] :: List[String], which already means you're not going to produce a List[List[String]] - so the right-hand side must be "wrapped" with a list to get the types right: d::List(e)
  • Prepending the other items follows the same rule - prepending List[String]s to a List[List[String]]
  • Once this is done - you get the expected result, without having to wrap the entire result with another list
Tzach Zohar
  • 37,442
  • 3
  • 79
  • 85
  • Thanks a lot for explanation, Now i really understand why List(a) in my program was needed and why List(e) has to be performed. Thanks again. – keerthi Oct 27 '16 at 19:08
1

If you are planning to achieve the end result using ::, adding a Nil at the end to the cons operation could yield the desired result.

a::b::c::a1::d::e::Nil

or you could wrap the last element in a List as @Tzach Zohar has mentioned.

a::b::c::a1::d::List(e)

Otherwise use

List(a,b,c,a1,d,e)
Johny T Koshy
  • 3,857
  • 2
  • 23
  • 40
1

Yes. If you really want to use that syntax:

List(a::b::c::a1::d::e::Nil: _*)

You need the : _* at the end because otherwise you are passing a single element (of type List) to List.apply() and it is not interpreting it as a sequence, which is why you get List[List[List]] instead of the desired List[List].

DK_
  • 2,648
  • 2
  • 21
  • 20