压缩两个长度递减的列表

Sar*_*ema 0 scala tail-recursion

我得到了下面应该用 Scala 解决的问题陈述:两个元素列表,第一个的大小小于第二个。例如列表 1 有 2 个元素,列表 2 有 10 个元素。需要将列表 1 的每个元素与第二个列表的两个元素进行映射。用于第一个元素的元素不应用于第二个元素,即它从第二个列表中获取两个唯一元素并返回第二个列表中的剩余元素以及映射元素列表。

scala> val list1 = List(1,2)
list1: List[Int] = List(1, 2)

scala> val list2 = List(3,4,5,6,7,8,9)
list2: List[Int] = List(3, 4, 5, 6, 7, 8, 9)
Run Code Online (Sandbox Code Playgroud)

预期产出

(List((1,3), (1,4), (2,5), (2,6)), List(7,8,9))
Run Code Online (Sandbox Code Playgroud)

Gur*_*ron 5

您从重复第一个列表的元素 n 次开始, flatMap 结果并用第二个集合压缩:

val list1 = List(1,2)
val list2 = List(3,4,5,6,7,8,9)

val zipped = list1
  .flatMap(i => (1 to list1.size).map(_ => i))
  .zip(list2) 
val result = (zipped, list2.drop(zipped.size))
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用“List.fill(list1.size)(i)”代替“(1 to list1.size).map(_ => i)”,我认为这更容易理解。 (4认同)

Lui*_*rez 5

这是我个人更喜欢使用尾递归方法解决的问题。

/** Zips two lists together by taking multiple elements from the second list
  * for each element of the first list.
  *
  * @param l1 The first (small) list.
  * @param l2 The second (big) list.
  * @param n The number of elements to take of second list for each element of teh first list,
  *          must be greater than zero.
  * @return A pair of the zipped list with the remaining elements of the second list,
  *         wrapped in an option to catch the possibility than the second list was consumed before finishing.
  */
def zipWithLarger[A, B](l1: List[A], l2: List[B])(n: Int): Option[(List[(A, B)], List[B])] = {  
  @annotation.tailrec
  def loop(remainingA: List[A], remainingB: List[B], count: Int, acc: List[(A, B)]): Option[(List[(A, B)], List[B])] =
    (remainingA, remainingB) match {
      case (a :: as, b :: bs) =>
        val newElement = (a, b)
        if (count == n)
          loop(remainingA = as, remainingB = bs, count = 1, newElement :: acc)
        else
          loop(remainingA, remainingB = bs, count + 1, newElement :: acc)
      
      case (Nil, _) =>
        Some(acc.reverse -> remainingB)
      
      case (_, Nil) =>
        // We consumed the second list beforing finishing the first one.
        None
    }

  // Ensure n is positive.
  if (n >= 1) loop(remainingA = l1, remainingB = l2, count = 1, acc = List.empty)
  else None
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处看到运行的代码