Элементы Zip с нечетными и четными индексами в списке - PullRequest
8 голосов
/ 08 апреля 2010

Я хочу сжать четные и нечетные элементы в списке, чтобы составить список пар, например:

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

Какое самое краткое выражение, чтобы сделать это элегантно и функционально?

Ответы [ 7 ]

7 голосов
/ 08 апреля 2010

В 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, поэтому он работает с пустыми списками.)

4 голосов
/ 08 апреля 2010

в Scala 2.8 вы можете сделать:

def pairs[T](xs: List[T]) =
  xs.grouped(2)
    .map{case List(a, b) => (a,b)}
    .toList
4 голосов
/ 08 апреля 2010

Непроверенные:

def ziptwo(l: List[String]): List[(String, String)] = l match {
    case Nil => Nil
    case a :: b :: rest =>
         Pair(a,b) :: ziptwo(rest)
}
3 голосов
/ 08 апреля 2010

Единственное преимущество того, что все придумали наиболее очевидные способы сделать это, заключается в том, что мне нужно больше думать о альтернативных решениях. Итак, вот тот, который работает на 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

Строго говоря, view / projection не требуется, но позволяет избежать ненужного создания промежуточных результатов.

Другие забавные способы сделать это:

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)
)

PS: Бонусное очко тому, кто получает каламбур. ; -)

1 голос
/ 08 апреля 2010

Это допускает неполные пары:

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 }   
1 голос
/ 08 апреля 2010
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!")
}
0 голосов
/ 22 декабря 2018

Использование 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

выход: * +1010 *

Array[(String, String)] = Array((A,B), (C,D), (E,F), (ODD,_))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...