代码之家  ›  专栏  ›  技术社区  ›  Alexander Temerev

列表中包含奇数和偶数索引的zip元素

  •  8
  • Alexander Temerev  · 技术社区  · 15 年前

    我想压缩列表中的偶数和奇数元素,以生成一个成对的列表,如下所示:

    ["A", "B", "C", "D", "E", "F"] -> [("A", "B"), ("C", "D"), ("E", "F")]
    

    最简洁的表达方式是什么?

    7 回复  |  直到 6 年前
        1
  •  7
  •   Rex Kerr    15 年前

    在2.8中,您可能会使用以下方法:

    scala> val a = "ABCDEF".toList.map(_.toString) 
    a: List[java.lang.String] = List(A, B, C, D, E, F)
    
    scala> a.grouped(2).partialMap{ case List(a,b) => (a,b) }.toList
    res0: List[(java.lang.String, java.lang.String)] = List((A,B), (C,D), (E,F))
    

    (这是2.8.0 Beta1;最新的行李箱 collect 代替 partialMap )

    在2.7中——在2.8中排名不错——您可以像Legoscia那样创建递归方法:

    def zipPairs[A](la : List[A]): List[(A,A)] = la match {
      case a :: b :: rest => (a,b) :: zipPairs(rest)
      case _ => Nil
    }
    
    scala> zipPairs(a)
    res1: List[(java.lang.String, java.lang.String)] = List((A,B), (C,D), (E,F))
    

    编辑:下面是另一个在2.7上也适用的简要方法:

    scala> (a zip a.drop(1)).zipWithIndex.filter(_._2 % 2 == 0).map(_._1)
    res2: List[(java.lang.String, java.lang.String)] = List((A,B), (C,D), (E,F))
    

    (注意使用 drop(1) 而不是 tail 所以它可以处理空列表。)

        2
  •  4
  •   Seth Tisue    15 年前

    在scala 2.8中,您可以执行以下操作:

    def pairs[T](xs: List[T]) =
      xs.grouped(2)
        .map{case List(a, b) => (a,b)}
        .toList
    
        3
  •  4
  •   missingfaktor Kevin Wright    15 年前

    未经测试的:

    def ziptwo(l: List[String]): List[(String, String)] = l match {
        case Nil => Nil
        case a :: b :: rest =>
             Pair(a,b) :: ziptwo(rest)
    }
    
        4
  •  3
  •   Daniel C. Sobral    15 年前

    让每个人都想出最明显的方法的唯一好处是,我必须更仔细地考虑其他解决方案。这是一个在scala 2.8上工作的。在scala 2.7上,更换 view 具有 projection .

    def everyNofM[T](l: List[T], n: Int, m: Int) = 
      l.view.zipWithIndex.filter(_._2 % m == n).map(_._1)
    def evens[T](l: List[T]) = everyNofM(l, 0, 2)
    def odds[T](l: List[T]) = everyNofM(l, 1, 2) 
    def zip[T](l: List[T]) = evens(l) zip odds(l) toList
    

    严格来说, 看法 / 投影 是不必要的,但它避免了中间结果的不必要创建。

    其他有趣的方法:

    def zip[T](l: List[T]) = l.indices.partition(_ % 2 == 0).zipped.map(
      (x: Int, y: Int) => (l(x), l(y))
    ).toList
    
    def zip[T](l: List[T]) = l.zipWithIndex.partition(_._2 % 2 == 0).zipped.map(
      (x, y) => (x._1, y._1)
    )
    

    附言:任何人都可以得到双关语。;-)

        5
  •  1
  •   missingfaktor Kevin Wright    15 年前
    def pairify[T](list: List[T]): List[(T, T)] = list match {
      case Nil => Nil
      case x :: y :: xs => (x, y) :: pairify(xs)
      case _ => error("odd length list!")
    }
    
        6
  •  1
  •   user unknown    15 年前

    这允许不完整的对:

    def pairwise [T] (xs: List[T]) : List [(Option[T], Option[T])] = xs match {
         case (x :: y :: xsr) => (Some (x), Some (y)) :: pairwise (xsr)             
         case (x :: Nil) => List ((Some (x), None))                                 
         case (_) => Nil }   
    
        7
  •  0
  •   RBarr    6 年前

    使用scala版本2.11.8

    val s = Seq("A", "B", "C", "D", "E", "F")
    s.sliding(2,2).map( l => (l.head,l.tail.head) ).toArray
    

    输出:

    Array[(String, String)] = Array((A,B), (C,D), (E,F))
    

    如果输入序列可以有奇数个元素,则需要更详细一点:

    val s = Seq("A", "B", "C", "D", "E", "F", "ODD")
    val defaultValue = "_"
    s.sliding(2,2).map( l => (l.head,l.tail.headOption.getOrElse(defaultStr)) ).toArray
    

    输出:

    Array[(String, String)] = Array((A,B), (C,D), (E,F), (ODD,_))