Scala 在列表的指定位置插入新元素
列表中没有内置函数或方法允许用户在列表的某个位置添加新元素。我已经编写了一个函数来实现这一点,但我不确定这样做是否是一个好主意,即使它工作得非常好:Scala 在列表的指定位置插入新元素,scala,Scala,列表中没有内置函数或方法允许用户在列表的某个位置添加新元素。我已经编写了一个函数来实现这一点,但我不确定这样做是否是一个好主意,即使它工作得非常好: def insert(list: List[Any], i: Int, value: Any) = { list.take(i) ++ List(value) ++ list.drop(i) } 用法: scala> insert(List(1,2,3,5), 3, 4) res62: List[Any] = List(1, 2, 3,
def insert(list: List[Any], i: Int, value: Any) = {
list.take(i) ++ List(value) ++ list.drop(i)
}
用法:
scala> insert(List(1,2,3,5), 3, 4)
res62: List[Any] = List(1, 2, 3, 4, 5)
类型安全
我看到的最明显的事情是缺乏类型安全性/类型信息丢失。我将使该方法在列表的元素类型中通用:
def insert[T](list: List[T], i: Int, value: T) = {
list.take(i) ++ List(value) ++ list.drop(i)
}
风格
如果主体仅由单个表达式组成,则不需要大括号:
def insert[T](list: List[T], i: Int, value: T) =
list.take(i) ++ List(value) ++ list.drop(i)
效率
关于使用避免遍历列表两次的注释也是一个很好的注释:
def insert[T](list: List[T], i: Int, value: T) = {
val (front, back) = list.splitAt(i)
front ++ List(value) ++ back
}
接口
一次插入多个值可能比较方便:
def insert[T](list: List[T], i: Int, values: T*) = {
val (front, back) = list.splitAt(i)
front ++ values ++ back
}
接口,取2
您可以将其作为列表的扩展方法
:
implicit class ListWithInsert[T](val list: List[T]) extends AnyVal {
def insert(i: Int, values: T*) = {
val (front, back) = list.splitAt(i)
front ++ values ++ back
}
}
List(1, 2, 3, 6).insert(3, 4, 5)
// => List(1, 2, 3, 4, 5, 6)
闭幕词
但是,请注意,插入到列表中间并不适合cons列表。你最好使用一个(可变的)链表或动态数组。你也可以使用
xs.patch(i,ys,r)
,它用补丁ys
替换xs
的r
元素,使用r=0
,并使ys
成为一个单件:
List(1, 2, 3, 5).patch(3, List(4), 0)
在
最多遍历一次。不是答案,但我建议使用
.splitAt
而不是。使用和删除(以避免在列表中重复两次)。这可能更合适。我将以该网站的精神回答:“没有内置函数或列表方法允许用户添加新元素”,但有这样一种方法-它被称为patch
。回答得很好。小挑剔:你可以用front++values++back
替换front++List(值:*)++back
。是的,谢谢。我太专注于保持原始版本。有点离题:为什么ListWithInsert
扩展AnyVal
?@dmitry:为什么不?毕竟,enrich my library是一开始引入值类的主要动机之一。谢谢,我还没有意识到这样的代码评审服务是存在的。在不久的将来,我肯定会用更多的scala示例来使用它
def insert(list: List[Any], i: Int, value: Any): List[Any] = list match {
case head :: tail if i > 0 => head :: insert(tail, i-1, value)
case _ => value :: list
}