Scala在特定位置插入列表

Mur*_*rgh 9 functional-programming scala list

这是我确实解决的问题,但是作为一个完全命令式的Scala noob,我觉得我发现了一些完全不优雅的东西.任何改进的想法都赞赏.

val l1 = 4 :: 1 :: 2 :: 3 :: 4 :: Nil // original list
val insert = List(88,99) // list I want to insert on certain places

// method that finds all indexes of a particular element in a particular list
def indexesOf(element:Any, inList:List[Any]) = {
        var indexes = List[Int]()
        for(i <- 0 until inList.length) {
                if(inList(i) == element) indexes = indexes :+ i
        }
        indexes
}


var indexes = indexesOf(4, l1) // get indexes where 4 appears in the original list

println(indexes)

var result = List[Any]()

// iterate through indexes and insert in front
for(i <- 0 until indexes.length) {
        var prev = if(i == 0) 0 else indexes(i-1)
        result = result ::: l1.slice(prev, indexes(i)) ::: insert
}
result = result ::: l1.drop(indexes.last) // append the last bit from original list

println(result)
Run Code Online (Sandbox Code Playgroud)

我认为更优雅的解决方案可以用这样的东西实现,但这只是纯粹的推测.

var final:List[Any] = (0 /: indexes) {(final, i) => final ::: ins ::: l1.slice(i, indexes(i))
Run Code Online (Sandbox Code Playgroud)

Rex*_*err 14

def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = {
  xs.map(x => if (p(x)) extra ::: List(x) else List(x)).flatten
}

scala> insert(List(4,1,2,3,4),List(88,99)){_ == 4}
res3: List[Int] = List(88, 99, 4, 1, 2, 3, 88, 99, 4)
Run Code Online (Sandbox Code Playgroud)

编辑:添加了解释.

我们的目标是extra在另一个列表中的所选元素前面插入一个列表(被调用)(这里称为 - xs通常用于列表,好像有一件事就是x它们中的许多必须是复数xs).我们希望这可以在我们可能拥有的任何类型的列表上工作,因此我们使用泛型类型对其进行注释[A].

哪些元素可以插入?在编写函数时,我们不知道,因此我们为每个元素(p: A => Boolean)提供一个函数,表示true或false .

现在,对于列表中的每个元素x,我们检查 - 我们应该插入(即为p(x)真)?如果是,我们只是构建它:extra ::: List(x)只是extra单个项目后跟的元素x.(最好把它写成 - extra :+ x最后添加单个项目.)如果不是,我们只有单个项目,但是我们创建它List(x)而不仅仅是x因为我们希望所有内容都具有相同的类型.所以现在,如果我们有类似的东西

4 1 2 3 4
Run Code Online (Sandbox Code Playgroud)

我们的条件是我们5 6之前插入4,我们生成

List(5 6 4) List(1) List(2) List(3) List(5 6 4)
Run Code Online (Sandbox Code Playgroud)

这正是我们想要的,除了我们有一个列表列表.为了摆脱内部列表并将所有内容压缩成一个列表,我们只需要调用flatten.

  • `xs.map(..).flatten`可以写成`xs.flatMap(..)`. (2认同)

Lan*_*dei 10

扁平的技巧很可爱,我不会想到map自己在这里使用.从我的角度来看,这个问题是折叠的典型应用,因为你想通过列表并"收集"某些东西(结果列表).由于我们不希望我们的结果列表向后,foldRight(又名:\)在这里是正确的版本:

def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = 
  xs.foldRight(List[A]())((x,xs) => if (p(x)) extra ::: (x :: xs) else x :: xs)
Run Code Online (Sandbox Code Playgroud)