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 组合函数,而不是编写自己的递归代码;这通常会使代码更清晰,并且通常与手动递归函数一样快或更快。
另请注意,我不会更改原始列表。这意味着我的函数适用于可变和不可变列表。如果您有一个可变列表,请随时将我返回的列表分配为您的 mutable 的新值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))
组合函数使事情变得更容易,但是当你使用正确的集合时,它变得如此简单,以至于几乎不值得编写一个特殊的函数。当然,除非你试图隐藏数据结构——在这种情况下,你真的应该把它隐藏在一个对象中。