What is the best way to allow only one of a specific value in an array?
For example, I would like to allow only one value of cat in the following array:
["dog", "cat", "cat", "hamster", "rabbit", "dog"]
such that it returned:
["dog", "cat", "hamster", "rabbit", "dog"]
EDIT: Apologies for not making this clear enough, I am not looking for uniq! I want to ensure that there is only 1 of a specified value.
To make only one value unique:
a = ["dog", "cat", "cat", "hamster", "rabbit", "dog"]
(a.count("cat") - 1).times { a.delete_at(a.index("cat"))}
#=> ["dog", "cat", "hamster", "rabbit", "dog"]
This preserves the order of the elements in the array.
To delete consecutive items:
Use Enumerable#chunk:
a = ["dog", "cat", "cat", "hamster", "rabbit", "dog"]
a.chunk(&:itself).map(&:first)
#=> ["dog", "cat", "hamster", "rabbit", "dog"]
Note that in Ruby < 2.2 you have to use chunk{|w| w} because itself isn't defined.
If you wish to modify the array in place:
def keep_one(arr, obj)
i = arr.each_index.find { |i| arr[i] == obj }
if i
arr.delete(obj)
arr.insert(i,obj)
end
end
arr = ["dog", "cat", "cat", 7.2, { a: 3}, "cat", "dog"]
a = arr.dup
keep_one(a,"cat")
a #=> ["dog", "cat", 7.2, {:a=>3}, "dog"]
a = arr.dup
keep_one(a,"dog")
a #=> ["dog", "cat", "cat", 7.2, {:a=>3}, "cat"]
a = arr.dup
keep_one(a,7.2)
a #=> ["dog", "cat", "cat", 7.2, {:a=>3}, "cat", "dog"]
a = arr.dup
keep_one(a,"pig")
a #=> ["dog", "cat", "cat", 7.2, {:a=>3}, "cat", "dog"]
If you do not wish to modify arr:
keep_one(arr.dup,"cat")
#=> ["dog", "cat", 7.2, {:a=>3}, "dog"]
arr
#=> ["dog", "cat", "cat", 7.2, {:a=>3}, "dog"]
or
def keep_one(arr, obj)
found = false
arr.each_with_object([]) do |o,a|
a << o unless o == obj && found
found = true if o == obj
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With