簡體   English   中英

根據 scala 中的元素類型將列表拆分為子列表

[英]Split a list into sublist based on element types in scala

如何根據元素類型將列表拆分為子列表?

簡而言之,鑒於:

trait Drink
final case object Coke extends Drink
final case object Pepsi extends Drink

val drinks = List(Coke,Coke,Pepsi,Coke,Pepsi,Pepsi)

我想:

List( List(Coke,Coke), List(Pepsi), List(Coke), List(Pepsi, Pepsi) )
    drinks.foldRight[List[List[Drink]](List.empty) {
       case (next, (l@(last :: _) :: tail) if next.getClass == last.getClass => 
          (next :: l)::tail
       case (next, rest) => List(next) :: rest
    }

如果類型是參數化的,您將需要注釋中提到的TypeTags ......但在這一點上,向 class 本身添加一個方法真的會更容易......類似於:

    class Drink[T: ClassTag] {
       def typeId = s"Drink of ${classTag[T].runtimeClass.getName}"
    }

然后你可以只比較這些類型 id 而不是實際的類。

drinks.foldRight(List.empty[List[Drink]]){
  case (c:Coke.type, ((hd:Coke.type)::tl)::acc)  => (c::hd::tl)::acc
  case (p:Pepsi.type,((hd:Pepsi.type)::tl)::acc) => (p::hd::tl)::acc
  case (d, acc) => List(d)::acc
}

有點冗長,部分原因是它們是案例對象。

您可以使用短尾遞歸 function,如下所示。

想法是使用next將“下一個飲品列表到 append 到結果”並acc將這些飲品列表累積到飲品列表中。

基本情況是一個空列表,其中返回結果。 否則,下一個飲料與下一個子列表匹配(將其添加到此子列表),或者不匹配(將子列表添加到結果並使用新飲料開始一個新的子列表)。

請注意:+是一個 List 方法,它返回一個附加了指定項目的新 List。

@tailrec
def get(list:List[Drink],
        next:List[Drink]=List(),
        acc: List[List[Drink]]=List()): List[List[Drink]] =
  list match {
    case Nil => acc :+ next   // dump final results
    case head :: tail =>
      if (next.isEmpty || next.head.getClass == head.getClass) get(tail, next :+ head, acc)
      else get(tail, List(head), acc :+ next)
  }


println(get(drinks))

結果:

List(List(Coke, Coke), List(Pepsi), List(Coke), List(Pepsi, Pepsi))

注意,注意到 jwvh 也有一個正確的答案,使用正確的模式匹配而不是這些條件。 在 List 上使用head方法可能是不安全的(或者編譯器很難確定安全性),但這種方法可能更簡潔,尤其是在存在多種 Drink 時。

如果你想避免直接使用head ,你可以這樣寫,我覺得這更令人困惑:

...
      if (next.headOption.map(h => h.getClass == head.getClass).getOrElse(true)) get(tail, next :+ head, acc)
...

為什么不在您的列表中使用groupBy

val rows = drinks.groupBy(x => x).values.toList

可以在這里測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM