2017-12-02 5 views
2

Ich habe eine Reihe von Zahlen, die durch Kommas getrennt, wie gezeigt:mehrere aufeinanderfolgende Einträge in Scala/spark

a: {108.109.110.112.114.115.116.118}

ich brauche die Ausgabe etwa wie folgt:

a: {108-110, 112, 114-116, 118}

Ich versuche die fortlaufenden Nummern mit "-" dazwischen zu gruppieren. Zum Beispiel 108.109.110 sind fortlaufende Nummern, so dass ich 108-110 bekomme. 112 ist ein separater Eintrag; 114,115,116 stellt wieder eine Sequenz dar, also bekomme ich 114-116. 118 ist getrennt und als solches behandelt.

Ich mache das in Spark. Ich schrieb den folgenden Code:

import scala.collection.mutable.ArrayBuffer 

def Sample(x:String):ArrayBuffer[String]={ 
    val x1 = x.split(",") 
    var a:Int = 0 
    var present="" 
    var next:Int = 0 
    var yrTemp = "" 
    var yrAr= ArrayBuffer[String]() 
    var che:Int = 0 
    var storeV = "" 
    var p:Int = 0 
    var q:Int = 0 

    var count:Int = 1 

    while(a < x1.length) 
    { 
     yrTemp = x1(a) 

     if(x1.length == 1) 
     { 
      yrAr+=x1(a) 
     } 
     else 
     if(a < x1.length - 1) 
     { 
      present = x1(a) 
      if(che == 0) 
      { 
       storeV = present 
      } 

      p = x1(a).toInt 
      q = x1(a+1).toInt 

      if(p == q) 
      { 
       yrTemp = yrTemp 
       che = 1 
      } 
      else 
      if(p != q) 
      { 
       yrTemp = storeV + "-" + present 
       che = 0 
       yrAr+=yrTemp 
      } 

     } 
     else 
      if(a == x1.length-1) 
      { 
       present = x1(a) 
       yrTemp = present 
       che = 0 
       yrAr+=yrTemp 
      } 
     a = a+1 
    } 
yrAr 
} 
val SampleUDF = udf(Sample(_:String)) 

Ich erhalte die Ausgabe wie folgt:

a: {108-108, 109-109, 110-110, 112, 114-114, 115- 115, 116-116, 118}

Ich bin nicht in der Lage herauszufinden, wo ich falsch liege. Können Sie mir bitte helfen, dies zu korrigieren? TIA.

+1

Bitte erläutern Sie die Regeln, die zu Ihrer erwarteten Ausgabe führen. Und das hängt nicht wirklich mit Funken zusammen, es ist nur ein Skalaproblem –

+0

@RaphaelRoth Ich habe die Regel in meiner Frage bearbeitet. –

Antwort

2

Hier ist eine andere Art und Weise:

def rangeToString(a: Int, b: Int) = if (a == b) s"$a" else s"$a-$b" 

def reduce(xs: Seq[Int], min: Int, max: Int, ranges: Seq[String]): Seq[String] = xs match { 
    case y +: ys if (y - max <= 1) => reduce(ys, min, y, ranges) 
    case y +: ys     => reduce(ys, y, y, ranges :+ rangeToString(min, max)) 
    case Seq()      => ranges :+ rangeToString(min, max) 
} 

def output(xs: Array[Int]) = reduce(xs, xs.head, xs.head, Vector())//.toArray 

Welche können Sie testen:

println(output(Array(108,109,110,112,114,115,116,118))) 
    // Vector(108-110, 112, 114-116, 118) 

Im Grunde ist dies eine rekursive Schwanz Funktion ist - das heißt Sie „Variablen“ als Eingangs nehmen, dann ruft er sich mit aktualisierten „Variablen“ auf jeder Schleife. Also hier xs ist Ihr Array, min und max sind ganze Zahlen verwendet, um die niedrigsten und höchsten Zahlen bis jetzt zu verfolgen, und ranges ist die Ausgangssequenz von Strings, die bei Bedarf hinzugefügt wird.

Das erste Muster (y das erste Element ist und ys der Rest der Sequenz ist - weil das, wie die +: Extraktor works) angepasst ist, wenn es zumindest ein Element ist (ys kann eine leere Liste sein) und es folgt, auf vom vorherigen Maximum.

Die zweite ist, wenn es nicht folgt, und muss das Minimum zurücksetzen und den fertigen Bereich zum Ausgang hinzufügen.

Der dritte Fall ist, wo wir das Ende der Eingabe haben und nur das Ergebnis ausgeben, anstatt die Schleife erneut aufzurufen.

Internet-Karma verweist auf jeden, der herausfinden kann, wie die Duplizierung von ranges :+ rangeToString(min, max) zu beseitigen ist!

1

hier eine Lösung:

def combineConsecutive(s: String): Seq[String] = { 
    val ints: List[Int] = s.split(',').map(_.toInt).toList.reverse 

    ints 
    .drop(1) 
    .foldLeft(List(List(ints.head)))((acc, e) => if ((acc.head.head - e) <= 1) 
     (e :: acc.head) :: acc.tail 
    else 
     List(e) :: acc) 
    .map(group => if (group.size > 1) group.min + "-" + group.max else group.head.toString) 
} 


val in = "108,109,110,112,114,115,116,118" 

val result = combineConsecutive(in) 

println(result) // List(108-110, 112, 114-116, 118) 

}

Diese Lösung nutzt teilweise Code aus dieser Frage: Grouping list items by comparing them with their neighbors

+0

Danke @raphael für die Lösung. Da ich ein Anfänger bin, hätte ich nie gedacht, dass es so leicht gemacht werden könnte. Danke noch einmal! –

Verwandte Themen