【问题标题】:How to flatten a nested tuple?如何展平嵌套元组?
【发布时间】:2012-11-21 20:27:45
【问题描述】:

我有一个像(String,(String,Double)) 这样的嵌套元组结构,我想将它转换为(String,String,Double)。我有各种嵌套元组,我不想手动转换每个。有什么方便的方法吗?

【问题讨论】:

    标签: scala tuples flatten


    【解决方案1】:

    answer above的补充

    粘贴此实用程序代码:

    import shapeless._
    import ops.tuple.FlatMapper
    import syntax.std.tuple._
    trait LowPriorityFlatten extends Poly1 {
      implicit def default[T] = at[T](Tuple1(_))
    }
    object flatten extends LowPriorityFlatten {
      implicit def caseTuple[P <: Product](implicit lfm: Lazy[FlatMapper[P, flatten.type]]) =
        at[P](lfm.value(_))
    }
    

    那么您就可以展平任何嵌套的元组:

    scala> val a = flatten(((1,2),((3,4),(5,(6,(7,8))))))
    a: (Int, Int, Int, Int, Int, Int, Int, Int) = (1,2,3,4,5,6,7,8)
    

    请注意,此方案不适用于自定义case class类型,会在输出中转换为String

    scala> val b = flatten(((Cat("c"), Dog("d")), Cat("c")))
    b: (String, String, String) = (c,d,c)
    

    【讨论】:

      【解决方案2】:

      在我看来,简单的模式匹配就可以了

      scala> val motto = (("dog", "food"), "tastes good")
      val motto: ((String, String), String) = ((dog,food),tastes good)
      
      scala> motto match {
           | case ((it, really), does) => (it, really, does)
           | }
      val res0: (String, String, String) = (dog,food,tastes good)
      

      或者如果你有一个这样的元组的集合:

      scala> val motto = List(
           | (("dog", "food"), "tastes good")) :+ (("cat", "food"), "tastes bad")
      val motto: List[((String, String), String)] = List(((dog,food),tastes good), ((cat,food),tastes bad))
      
      scala> motto.map {
           | case ((one, two), three) => (one, two, three)
           | }
      val res2: List[(String, String, String)] = List((dog,food,tastes good), (cat,food,tastes bad))
      

      我认为即使你有几个案例也会很方便。

      【讨论】:

        【解决方案3】:

        不确定这样做的效率,但您可以将Tuple 转换为Listtuple.productIterator.toList,然后flatten 嵌套列表:

        scala> val tuple = ("top", ("nested", 42.0))
        tuple: (String, (String, Double)) = (top,(nested,42.0))
        
        scala> tuple.productIterator.map({
             |   case (item: Product) => item.productIterator.toList
             |   case (item: Any) => List(item)
             | }).toList.flatten
        res0: List[Any] = List(top, nested, 42.0)
        

        【讨论】:

        • 不幸的是,使用这种方法,您将失去元素的静态类型。
        【解决方案4】:

        如果您使用shapeless,我认为this 正是您所需要的。

        【讨论】:

        • 你应该放一些代码示例。仅链接答案不遵循 stackoverflow 指南
        • @Juh_ 查看代码示例here
        【解决方案5】:

        元组上没有展平。但如果你知道结构,你可以这样做:

        implicit def flatten1[A, B, C](t: ((A, B), C)): (A, B, C) = (t._1._1, t._1._2, t._2)
        implicit def flatten2[A, B, C](t: (A, (B, C))): (A, B, C) = (t._1, t._2._1, t._2._2)
        

        这将使任何类型的 Tuple 变平。您还可以将隐式关键字添加到定义中。这仅适用于三个元素。你可以像这样扁平化元组:

        (1, ("hello", 42.0))   => (1, "hello", 42.0)
        (("test", 3.7f), "hi") => ("test", 3.7f, "hi")
        

        多个嵌套的Tupple不能展平到地面,因为返回类型只有三个元素:

        ((1, (2, 3)),4)        => (1, (2, 3), 4)
        

        【讨论】:

          猜你喜欢
          • 2019-03-05
          • 2017-10-10
          • 2020-10-04
          • 1970-01-01
          • 1970-01-01
          • 2018-11-09
          • 2018-05-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多