73223

How do I remove an element from a Vector?

Question:

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).

Answer1:

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 <em>was</em> 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. <strong>Edit:</strong> I checked it out, and saw that - is now reserved for a <em>mutable</em> 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. :-)

Answer2:

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.)

Answer3:

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)

Answer4:

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 <em>set</em> 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!

Answer5:

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.

Recommend

  • Dependencies error while running “mvn compile”
  • Apache graceful restart - Does it affect current PHP script execution
  • Why does Perl's IO::Socket on Windows complain about “Resource Not Available” after 64 connecti
  • Open a Configuration Profile through app
  • autocomplete with ajax. jQuery plugin or jQuery UI widget?
  • Change font size to fit text inside button entirely?
  • Rectangular Nesting - Convergence to optimal solution using Simulated Annealing
  • How is a header file being compiled into the executable file?
  • Testing Meteor packages with Velocity?
  • The C Programming Language K&R exercise 1- 9
  • Column Nullability/Optionality: NULL vs NOT NULL
  • stringify/parse edn in clojure/ClojureScript
  • How can I sum two different columns at once where one contains Decimal objects in pandas?
  • Capturing HTML Text Input Key press after key has been applied?
  • How to have a website splash screen (web app)
  • SQL Server 2008 R2 - Islands and Gaps [closed]
  • reduce/reduce conflicts using ocamlyacc
  • How to write string.Contains(someText) in expression Tree
  • How to get the index of element in the List in c#
  • Using an enum contained in a Cloud Endpoint model on a Android client
  • Rails AREL .where statement
  • Client side validation mvc dropdown
  • How gzip file gets stored in HDFS
  • Pre-populated SQLite Database not reading properly in Android Studio
  • Deploying a CodeRush plugin from the Community Site
  • Laravel 4 routing not working due to .htaccess file?
  • Retrieving specified columns from a list of csv files to create a data data frame in R
  • How to override value that appears in a dropdown in the rails_admin gem
  • Filter strings with regex before casting to numeric
  • C# program and C++ DLL compiled for 32-bit system crash on 64-bit system
  • C: Incompatible pointer type initializing
  • why xml file does not aligned properly after append the string in beginning and end of the file usin
  • How do I open a C file with a relative path?
  • Fetching methods from BroadcastReceiver to update UI
  • Get object from AWS S3 as a stream
  • Symfony2: How to get request parameter
  • Weird JavaScript statement, what does it mean?
  • GridView Sorting works once only
  • WPF Applying a trigger on binding failure
  • Django query for large number of relationships