开发者

Buiding a stack in a map

I 开发者_C百科have a string that looks like this:

 "7-6-4-1"

or

 "7"

or

 ""

That is, a set of numbers separated by -. There may be zero or more numbers.

I want to return a stack with the numbers pushed on in that order (i.e. push 7 first and 1 ast, for the first example)

If I just wanted to return a list I could just go str.split("-").map{_.toInt} (although this doesn't work on the empty string)/

There's no toStack to convert to a Stack though. So currently, I have

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

Which works, but is pretty ugly. What am I missing?

EDIT: Thanks to all the responders, I learnt quite a bit from this discussion


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

The trick here is to pass the array you get from split into the Stack companion object builder. By default the items go in in the same order as the array, so you have to reverse the array first.

Note the "treat this is a list, not as a single item" annotation, : _*.


Edit: if you don't want to catch the empty string case separately, like so (use the bottom one for mutable stacks, the top for immutable):

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

then you can filter out empty strings:

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

which will also "helpfully" handle things like 7-9----2-2-4 for you (it will give Stack(4,2,2,9,7)).

If you want to handle even more dastardly formatting errors, you can

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

to return only those items that actually can be parsed.


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


Dont forget the ever handy breakOut which affords slightly better performance than col: _* (see Daniel's excellent explanation)

Used here with Rex Kerr's .filterNot(_.isEmpty) solution:

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(""))
  }
}

Will output:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜