2010-12-06 83 views
1

J'ai une chaîne qui ressemble à ceci:buiding une pile dans une carte

"7-6-4-1" 

ou

"7" 

ou

"" 

C'est un ensemble de nombres séparés par -. Il peut y avoir zéro ou plusieurs nombres.

Je veux retourner une pile avec les numéros poussé dans cet ordre (c.-à pousser 7 premier et 1 ast, pour le premier exemple)

Si je voulais juste retourner une liste que je pouvais aller str.split("-").map{_.toInt} (bien que cela ne fonctionne pas sur la chaîne vide)/

Cependant, il n'y a pas de toStack à convertir en pile. Donc actuellement, j'ai

{ 
    val s = new Stack[Int]; 
    if (x.nonEmpty) 
     x.split('-').foreach { 
    y => s.push(y.toInt) 
     } 
    s 
    } 

Qui fonctionne, mais est assez moche. Qu'est-ce que je rate?

EDIT: Merci à tous les intervenants, je l'ai appris tout à fait un peu de cette discussion

Répondre

5
Stack(x.split("-").map(_.toInt).reverse: _*) 

L'astuce est ici pour passer le tableau que vous obtenez de scission dans le générateur d'objet compagnon Stack. Par défaut, les éléments entrent dans le même ordre que le tableau, vous devez donc d'abord inverser le tableau.

Notez l'annotation "traiter cette liste, pas comme un seul article", : _*.


Edit: si vous ne voulez pas attraper le cas de chaîne vide séparément, comme si (utilisez celle du bas pour les piles mutables, sommet pour immuable):

if (x.isEmpty) Stack() else Stack(x.split("-").map(_.toInt).reverse: _*) 
if (x.isEmpty) Stack[Int]() else Stack(x.split("-").map(_.toInt).reverse: _*) 

alors vous pouvez filtrer les chaînes vides:

Stack(x.split("-").filterNot(_.isEmpty).map(_.toInt).reverse: _*) 

qui sera également gérer « obligeamment » des choses comme 7-9----2-2-4 pour vous (il donnera Stack(4,2,2,9,7)).

Si vous souhaitez traiter encore plus ignobles erreurs de mise en forme, vous pouvez

val guard = scala.util.control.Exception.catching[Int](classOf[NumberFormatException]) 
Stack(x.split("-").flatMap(x => guard.opt(x.toInt)).reverse: _*) 

retourner uniquement les éléments qui peuvent réellement être analysés.

+0

Merci. J'ai encore besoin du chèque non-vide pour x? –

+1

@Paul oui, le contrôle nonEmpty n'est pas là –

+0

'x => {Stack (x.split (" - "). Collecter {case x si x.nonEmpty => x.toInt} .reverse: _ *)}' bit . semble couvrir le cas nonEmpty :) –

3
(Stack[Int]() /: (if(x.isEmpty) Array.empty else x.split("-")))(
        (stack, value) => 
         stack.push(value toInt)) 
+0

Merci . C'est X qui peut être vide, pas la ficelle une fois fendue? et pouvez-vous l'expliquer un peu? :) –

+0

@Paul 'foldLeft' est utilisé pour remplir récursivement une nouvelle pile vide avec les valeurs provenant de la séparation de la chaîne. –

3

Ne pas oublier le toujours à portée de main breakOut qui offre une performance légèrement meilleure que col: _* (voir Daniel's excellent explanation)

Utilisé ici avec une solution de Rex Kerr .filterNot(_.isEmpty):

import scala.collection.immutable.Stack 
import scala.collection.breakOut 

object StackFromString { 

    def stackFromString(str: String): Stack[Int] = 
    str.split("-").filterNot(_.isEmpty) 
     .reverse.map(_.toInt)(breakOut) 

    def main(args: Array[String]): Unit = { 
    println(stackFromString("7-6-4-1")) 
    println(stackFromString("7")) 
    println(stackFromString("")) 
    } 
} 

sortie Will:

Stack(1, 4, 6, 7) 
Stack(7) 
Stack()