2013-06-12 4 views
1

Я хочу условно объединить элементы, следующие за каждым в списке, на основе некоторого выражения. пример, чтобы лучше объяснить, что я хотел бы сделать:Условно элементы списка слияния

от:

val list = List("a1", "a2", "b1", "b2", "b3", "a3", "a4")

Я хотел бы объединить все элементы, начиная с Ь в один элемент, чтобы получить результирующий список, как это:

List("a1", "a2", "b1-b2-b3", "a3", "a4") 

в моем случае использования, B-элементы всегда следуют последовательно, но число би-элементов может изменяться от каких-либо элементов до десятков элементов.

Я пытался сделать что-то вроде

list.foldLeft("")((s1, s2) => if (s1.matches("""b\d""") && s2.matches("""b\d""")) s1 + "-" + s2 else s1) 

но это не делает мне ничего полезного.

Любые предложения о том, как подойти к этому?

ответ

2

Это может быть сделано с foldLeft и глядя на последней вставленной элемент списка:

list.foldLeft(List[String]()) { 
    case (Nil, str) => str :: Nil 
    case (head :: tail, str) => 
    if (head(0) == 'b' && str(0) == 'b') (s"$head-$str") :: tail 
    else str :: head :: tail 
}.reverse 
//> res0: List[String] = List(a1, a2, b1-b2-b3, a3, a4) 

Матч шаблон также можно переписать (если вам понятнее):

list.foldLeft(List[String]()) { 
    case (head :: tail, str) if (head(0) == 'b' && str(0) == 'b') => 
    (s"$head-$str") :: tail 
    case (other, str) => 
    str :: other 
}.reverse  
+0

Спасибо, первый пример отлично работает! – Lundahl

0

Это должно работать

def aggregateByPrefix(xs: Seq[String], prefix: String) = { 
    val (xs1, xs2) = xs.span(x => !x.startsWith(prefix)) 
    val (withPrefix, withoutPrefix) = xs2.partition(_.startsWith(prefix)) 
    val aggregated = withPrefix.mkString("-") 
    xs1 ++ Seq(aggregated) ++ withoutPrefix 
} 

Использование:

aggregateByPrefix(List("a1", "a2", "b1", "b2", "b3", "a3", "a4"), "b") 
=> List(a1, a2, b1-b2-b3, a3, a4) 
Смежные вопросы