List 如果任何键只应存在一次,则使用错误的集合。你应该使用Map[String,Any]。有一个列表,
- 您必须做额外的工作以防止重复条目。
- 检索密钥会更慢,它显示在列表的下方。尝试检索不存在的键将与列表的大小成比例地变慢。
我猜第 2 点可能是您尝试将其替换为 Nil 而不仅仅是从列表中删除密钥的原因。 Nil 真的不适合在这里使用。如果您尝试检索不存在的密钥与已删除的密钥相比,您将得到不同的东西。这真的是你想要的吗?返回Some(Nil) 有多大意义?
这里有一些方法适用于可变或不可变列表,但它们并不假设您已成功阻止重复出现...
val l1: List[(String, Any)] = List(("apple", 1), ("pear", "violin"), ("banana", Unit))
val l2: List[(Int, Any)] = List((3, 1), (4, "violin"), (7, Unit))
def remove[A,B](key: A, xs: List[(A,B)]) = (
xs collect { case x if x._1 == key => x._2 },
xs map { case x if x._1 != key => x; case _ => (key, Nil) }
)
scala> remove("apple", l1)
res0: (List[(String, Any)], List[(String, Any)]) = (List((1)),List((apple, List()),(pear,violin), (banana,object scala.Unit)))
scala> remove(4, l2)
res1: (List[(Int, Any)], List[(Int, Any)]) = (List((violin)),List((3,1), (4, List()), (7,object scala.Unit)))
scala> remove("snark", l1)
res2: (List[Any], List[(String, Any)]) = (List(),List((apple,1), (pear,violin), (banana,object scala.Unit)))
返回匹配值的列表(如果不匹配,则返回一个空列表而不是None)和剩余的列表,在一个元组中。如果您想要一个完全删除不需要的密钥的版本,请执行此操作...
def remove[A,B](key: A, xs: List[(A,B)]) = (
xs collect { case x if x._1 == key => x._2 },
xs filter { _._1 != key }
)
但也要看看这个:
scala> l1 groupBy {
case (k, _) if k == "apple" => "removed",
case _ => "kept"
}
res3: scala.collection.immutable.Map[String,List[(String, Any)]] = Map(removed -> List((apple,1)), kept -> List((pear,violin), (banana,object scala.Unit)))
这是你可以开发的东西。您需要做的就是将("apple", Nil) 添加到“保留”列表中并从“删除”列表中提取值。
请注意,我使用的是 List 组合函数,而不是编写自己的递归代码;这通常会使代码更清晰,并且通常与手动递归函数一样快或更快。
还请注意,我不会更改原始列表。这意味着我的函数适用于可变和不可变列表。如果您有一个可变列表,请随时将我返回的列表分配为您的可变 var 的新值。赢了,赢了。
但是请为此使用地图。看看事情变得多么简单:
val m1: Map[String, Any] = Map(("apple", 1), ("pear", "violin"), ("banana", Unit))
val m2: Map[Int, Any] = Map((3, 1), (4, "violin"), (7, Unit))
def remove[A,B](key: A, m: Map[A,B]) = (m.get(key), m - key)
scala> remove("apple", m1)
res0: (Option[Any], scala.collection.immutable.Map[String,Any]) = (Some(1),Map(pear -> violin, banana -> object scala.Unit))
scala> remove(4, m2)
res1: (Option[Any], scala.collection.immutable.Map[Int,Any]) = (Some(violin),Map(3 -> 1, 7 -> object scala.Unit))
scala> remove("snark", m1)
res2: res26: (Option[Any], scala.collection.immutable.Map[String,Any]) = (None,Map(apple -> 1, pear -> violin, banana -> object scala.Unit))
组合函数使事情变得更容易,但是当你使用正确的集合时,它变得如此简单,以至于几乎不值得编写一个特殊的函数。当然,除非您试图隐藏数据结构——在这种情况下,您应该将其真正隐藏在对象中。