Reputation: 16841
I have a Set of elements from which I want to take and remove the first few elements a bunch of times. Is there a shorter way (so one operation instead of two) to do that than this:
require 'set'
s = Set[1, 2, 3, 4] # => #<Set: {1, 2, 3, 4}>
first_two = s.take(2) # => [1, 2]
s.subtract(first_two) # => #<Set: {3, 4}>
(So basically I'm wondering whether I'm overlooking a shift
for Sets)
Upvotes: 5
Views: 3723
Reputation: 7725
From http://www.ruby-doc.org/stdlib-1.9.3/libdoc/set/rdoc/Set.html:
Set implements a collection of unordered values with no duplicates. This is a hybrid of Array's intuitive inter-operation facilities and Hash's fast lookup.
It would be odd and probably illogical to implement methods like shift and pop on an object that knows nothing about index.
Upvotes: 1
Reputation: 79562
There is no shorter way using builtin methods.
There is an open feature request for a method to return and remove one element; you may want to help refine the API?
Upvotes: 3
Reputation: 183
I'm late to the party, but here's my solution. Convert the set to an array first, and then all Enumerable methods are available. Take 2 from the array and then be sure to also remove the from the set. The two values from the set get removed and returned.
require 'set'
s = Set[1, 2, 3, 4] # => #<Set: {1, 2, 3, 4}>
first_two = s.to_a.take(2).tap {|a| s.subtract(a)} # => [1, 2]
s # => #<Set: {3, 4}>
Upvotes: 0
Reputation: 740
You could add a new method take!
(or remove!
or whatever name seems appropriate) to the Set class:
class Set
def take!(args)
taken = self.take(args)
self.subtract(taken)
return taken
end
end
a = Set[1, 2, 3, 4] # <Set: {1, 2, 3, 4}>
a.take!(2) # <Set: {1, 2}>
a # <Set: {3, 4}>
Upvotes: 5