Scala List function for grouping consecutive identical elements

后端 未结 8 2246
悲&欢浪女
悲&欢浪女 2020-12-05 08:00

Given e.g.:

List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)

I\'d like to get to:

List(List(5), List(2), List(3, 3, 3), List(5, 5),         


        
相关标签:
8条回答
  • 2020-12-05 08:26

    Damn Rex Kerr, for writing the answer I'd go for. Since there are minor stylistic differences, here's my take:

    list.tail.foldLeft(List(list take 1)) { 
        case (acc @ (lst @ hd :: _) :: tl, el) => 
            if (el == hd) (el :: lst) :: tl 
            else (el :: Nil) :: acc 
    }
    

    Since the elements are identical, I didn't bother reversing the sublists.

    0 讨论(0)
  • 2020-12-05 08:31

    Here's a tail-recursive solution inspired by @Kevin Wright and @Landei:

    @tailrec
    def sliceEqual[A](s: Seq[A], acc: Seq[Seq[A]] = Seq()): Seq[Seq[A]] = {
      s match {
        case fst :: rest =>
          val (l, r) = s.span(fst==)
          sliceEqual(r, acc :+ l)
        case Nil => acc
      }
    }
    
    0 讨论(0)
  • 2020-12-05 08:31

    Here's a slightly cleaner one:

    def groupConsequtive[A](list: List[A]): List[List[A]] = list match {
      case head :: tail =>
        val (t1, t2) = tail.span(_ == head)
        (head :: t1) :: groupConsequtive(t2)
      case _ => Nil  
    }
    

    tail-recursive version

    @tailrec
    def groupConsequtive[A](list: List[A], acc: List[List[A]] = Nil): List[List[A]] = list match {
      case head :: tail =>
        val (t1, t2) = tail.span(_ == head)
        groupConsequtive(t2, acc :+ (head :: t1))
      case _ => acc
    }
    
    0 讨论(0)
  • 2020-12-05 08:36
    val xs = List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
    

    Here's another way.

    (List(xs.take(1)) /: xs.tail)((l,r) =>
      if (l.head.head==r) (r :: l.head) :: l.tail else List(r) :: l
    ).reverseMap(_.reverse)
    
    0 讨论(0)
  • 2020-12-05 08:37
    list.foldRight(List[List[Int]]()){
      (e, l) => l match {
        case (`e` :: xs) :: fs => (e :: e :: xs) :: fs
        case _ => List(e) :: l
      }
    }
    

    Or

    list.zip(false :: list.sliding(2).collect{case List(a,b) => a == b}.toList)
     .foldLeft(List[List[Int]]())((l,e) => if(e._2) (e._1 :: l.head) :: l.tail 
                                           else List(e._1) :: l ).reverse
    

    [Edit]

    //find the hidden way 
    //the beauty must be somewhere
    //when we talk scala
    
    def split(l: List[Int]): List[List[Int]] = 
      l.headOption.map{x => val (h,t)=l.span{x==}; h::split(t)}.getOrElse(Nil)
    
    0 讨论(0)
  • 2020-12-05 08:38

    this could be simpler:

    val input = List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
    input groupBy identity values
    
    0 讨论(0)
提交回复
热议问题