How do I remove an element from a Vector?

回眸只為那壹抹淺笑 提交于 2019-12-11 13:12:17

问题


This is what I'm doing now:

  private var accounts = Vector.empty[Account]

  def removeAccount(account: Account)
  {
    accounts = accounts.filterNot(_ == account)
  }

Is there a more readable solution? Ideally, I'd like to write accounts = accounts.remove(account).


回答1:


I'd use this:

accounts filterNot account.==

Which reads pretty well to me, but ymmv. I'd also like a count that doesn't take a predicate, but the collection library is really lacking in specialized methods where one with a predicate can generalize the operation.

Until 2.8.x, there was a - method, which got deprecated, iirc, because of semantic issues. It could actually have come back on 2.10 if my memory is serving me right, but it didn't. Edit: I checked it out, and saw that - is now reserved for a mutable method that modifies the collection it is applied on. I'd be all in favor of -:/:- though on sequences, where it makes sense to drop the first or last element equal to something. Anyone willing to front a ticket for that? I'd upvote it. :-)




回答2:


There unfortunately is not, and worse still (perhaps), if the same account is present twice, filterNot will remove both of them. The only thing I can offer for readability is to use

accounts.filter(_ != account)

Another possibility is to use a collection type that does have a remove operation, such as a TreeSet (where it is called -). If you don't have duplicate entries anyway, a Set is perfectly okay. (It is slower for some operations, of course, but it probably is a better fit to the application--it's more efficient at removing individual entries; with a filterNot you basically have to build the entire Vector again.)




回答3:


You could do something like this:

def removeFirst[T](xs: Vector[T], x: T) = {
  val i = xs.indexOf(x)
  if (i == -1) xs else xs.patch(i, Nil, 1)
}

then

accounts = removeFirst(accounts, account)

I think the nub of the problem, though, is that a Vector probably isn't the right collection type for a set of items where you want to pull things out (hint: try Set). If you want to index on an ID or an insertion index then Map could be what you're after (which does have a - method). If you want to index on multiple things efficiently, you need a database!




回答4:


You can use the diff method which is defined for all sequences. It computes the multiset difference between two sequences - meaning it will remove as many occurrences of an element as you need.

Vector(1, 2, 1, 3, 2).diff(Seq(1)) => 
Vector(2, 1, 3, 2)

Vector(1, 2, 1, 3, 2).diff(Seq(1, 1)) =>
Vector(2, 3, 2)

Vector(1, 2, 1, 3, 2).diff(Seq(1, 1, 2))  
Vector(3, 2)



回答5:


If you prefer not to use the filterNot closure, you could use the more verbose yet more explicit for-comprehension style instead.

private var accounts = Vector.empty[Account]

def removeAccount(account: Account)
{
    accounts = for { a <- accounts
                     if a != account } yield { a }
}

It's a matter of personal preference whether this is felt to be better in this case.

Certainly for more complex expressions involving nested flatMaps etc, I agree with Martin Odersky's advice that for-comprehensions can be quite a bit easier to read, especially for novices.



来源:https://stackoverflow.com/questions/15364252/how-do-i-remove-an-element-from-a-vector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!