【问题标题】:Manipulating tuples操作元组
【发布时间】:2011-08-20 05:16:49
【问题描述】:

有没有办法在不使用临时变量和启动新语句的情况下操作元组的多个值?

假设我有一个返回元组的方法,我想内联处理这些值。

例如如果我想在某个点拆分字符串并反转片段

def backToFront(s: String, n:Int) = s.splitAt(n)...

我可以的

val (a, b) = s.splitAt(n)
b + a 

(需要临时变量和新语句)或

List(s.splitAt(n)).map(i => i._2 + i._1).head

(有效,但似乎有点脏,为此创建一个元素列表)或

s.splitAt(n).swap.productIterator.mkString

(适用于这个特定示例,但只是因为恰好有一个 swap 方法可以满足我的要求,所以它不是很通用)。

元组上的zipped 方法似乎只适用于列表元组。

再举一个例子,如何在一个语句中将元组('a, 'b, 'c) 变成('b, 'a, 'c)

【问题讨论】:

    标签: scala tuples


    【解决方案1】:

    元组只是方便的返回类型,并不假定你会用它进行复杂的操作。 scala 论坛上也有类似的discussion

    关于最后一个例子,找不到比模式匹配更好的东西了。

    ('a, 'b, 'c) match { case (a, b, c) => (b, a ,c) }
    

    【讨论】:

    • 模式匹配好! s.splitAt(n) match {case(a,b) => b + a} 适用于第一部分
    • 可惜标准库中没有fold方法;然后你可以s.splitAt(n).fold((a,b) => b + a),它也会更有效率。 (是的,当然我自己做了。)
    【解决方案2】:

    不幸的是,元组的内置方法是pretty limited

    也许你想在你的个人图书馆里有这样的东西,

    def fold2[A, B, C](x: (A, B))(f: (A, B) => C): C = f(x._1, x._2)
    def fold3[A, B, C, D](x: (A, B, C))(f: (A, B, C) => D): D = f(x._1, x._2, x._3)
    

    通过适当的隐式转换,您可以做到,

    scala> "hello world".splitAt(5).swap.fold(_ + _)
    res1: java.lang.String = " worldhello"
    
    scala> (1, 2, 3).fold((a, b, c) => (b, c, a))
    res2: (Int, Int, Int) = (2,3,1)
    

    最后一个表达式的替代方法是“管道”运算符 |>(从 Scalaz 或 here 获取),

    scala> ('a, 'b, 'c) |> (t => (t._2, t._3, t._1))
    res3: (Symbol, Symbol, Symbol) = ('b,'c,'a)
    

    如果没有所需的注释,这会很好,

    scala> ("hello ", "world") |> (((_: String) + (_: String)).tupled)
    res4: java.lang.String = hello world
    

    【讨论】:

      【解决方案3】:

      这个怎么样?

      s.splitAt(n) |> Function.tupled(_ + _)
      

      [ 编辑:刚刚注意到你的函数参数是相反的。在这种情况下,您将不得不放弃占位符语法,转而使用:s.splitAt(n) |> Function.tupled((a, b) => b + a)]

      对于您的最后一个示例,想不出比模式匹配更好的方法(如 @4e6 所示。)

      【讨论】:

        【解决方案4】:

        使用shapeless的当前开发版本,无需解包元组即可实现:

        import shapeless.syntax.std.tuple._
        
        val s = "abcdefgh"
        val n = 3
        
        s.splitAt(n).rotateRight[shapeless.Nat._1].mkString("", "", "") // "defghabc"
        

        我认为在最后一行方法的语法被清理之前,你不应该等待太久(我会说是几天),你可以简单地写

        s.splitAt(n).rotateRight(1).mkString
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-04
          • 2012-06-30
          相关资源
          最近更新 更多