插入的反转是什么,以及如何实现它?

时间:2014-07-18 15:07:30

标签: scala functional-programming

This question讨论了如何以交替的方式交错两个列表,即嵌入它们。

  • " intercalate"的反转是什么?叫?
  • 在Scala中实现这个是否有惯用的方法?

3 个答案:

答案 0 :(得分:5)

Haskell IRC session上讨论了这个主题。

可能性包括" deintercalate"," extracalate"," ubercalate"," outercalate"," chocolate" ; - )

假设我们选择" extracalate",它可以实现为折叠:

def extracalate[A](a: List[A]) = 
    a.foldRight((List[A](), List[A]())){ case (b, (a1,a2)) => (b :: a2, a1) }

例如:

val mary = List("Mary", "had", "a", "little", "lamb")
extracalate(mary)                              
//>  (List(Mary, a, lamb),List(had, little)

请注意,原始列表只能在以下情况下重建:

  • 输入列表的长度相同,或
  • 第一个列表比第二个列表长1个

第二种情况实际上证明对geohashing算法有用,其中纬度位和经度位被插入,但可能有奇数位。

另请注意,链接问题中intercalate的定义与Haskell libraries中的定义不同,后者在列表列表之间插入了一个列表!

更新:对于任何折叠,我们提供一个起始值和一个应用于输入列表的每个值的函数。此功能修改起始值并将其传递到折叠的下一步。 在这里,我们从一对空输出列表开始:(List[A](), List[A]()) 然后,对于输入列表中的每个元素,我们使用cons ::将其添加到其中一个输出列表的前面。但是,每次调用函数时,我们也会交换两个输出列表的顺序; (a1, a2)变为(b :: a2, a1)。这以交替的方式在两个输出列表之间划分输入列表。因为它是折叠,所以我们从输入列表的末尾开始,这是以正确的顺序获取每个输出列表所必需的。从起始值到最终值,我们得到:

([], [])
([lamb], [])
([little],[lamb])
([a, lamb],[little])
([had, little],[a, lamb])
([Mary, a, lamb],[had, little])

答案 1 :(得分:2)

另外,使用标准方法

val mary = List("Mary", "had", "a", "little", "lamb")
       //> mary  : List[String] = List(Mary, had, a, little, lamb)
val (f, s) = mary.zipWithIndex.partition(_._2 % 2 == 0)
       //> f  : List[(String, Int)] = List((Mary,0), (a,2), (lamb,4))
       //| s  : List[(String, Int)] = List((had,1), (little,3))
(f.unzip._1, s.unzip._1) 
       //> res0: (List[String], List[String]) = (List(Mary, a, lamb),List(had, little))

不是真的推荐它,但是,折叠将在性能上击败它

以另一种方式剥皮猫

val g = mary.zipWithIndex.groupBy(_._2 % 2) 
        //> g  : scala.collection.immutable.Map[Int,List[(String, Int)]] = Map(1 -> List
        //| ((had,1), (little,3)), 0 -> List((Mary,0), (a,2), (lamb,4)))
 (g(0).unzip._1, g(1).unzip._1)
       //> res1: (List[String], List[String]) = (List(Mary, a, lamb),List(had, little))

也会慢一点

答案 2 :(得分:0)

我认为它不如@DNA的答案,因为它的代码更多,而且需要两次通过列表。

scala> list
res27: List[Int] = List(1, 2, 3, 4, 5)

scala> val first = list.zipWithIndex.filter( x => x._1 % 2 == 1).map(x => x._2)
first: List[Int] = List(0, 2, 4)

scala> val second = list.zipWithIndex.filter( x => x._1 % 2 == 0).map(x => x._2)
second: List[Int] = List(1, 3)

scala> (first, second)
res28: (List[Int], List[Int]) = (List(0, 2, 4),List(1, 3))