Reputation: 6568
I have the following array
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"]
I want to remove blank elements from the array and want the following result:
cities = ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Is there any method like compact
that will do it without loops?
Upvotes: 346
Views: 280715
Reputation: 2732
cities.delete_if(&:blank?)
This will remove both nil
values and empty string (""
) values.
For example:
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal", nil]
cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Starting from version of Rails 6.1 ActiveSupport offers compact_blank
.
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal", nil]
cities.compact_blank
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Upvotes: 29
Reputation: 201
Update in reject and reject!
NOTE: I came across this question and checked these methods on the irb console with
ruby-3.0.1
. I also checked the ruby docs but this is not mentioned there. I am not sure from which ruby version this change is there. Any help from the community is much appreciated.
With ruby-3.0.1
we can use either reject
or reject!
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"]
cities.reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
or shorthand
cities.reject(&:empty?)
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
both will return []
no matter we have an empty value or not?
Upvotes: 2
Reputation: 9228
If you are using Rails
(or a standalone ActiveSupport
), starting from version 6.1
, there is a compact_blank
method that removes blank
values from arrays.
It uses Object#blank?
under the hood for determining if an item is blank.
["Kathmandu", "Pokhara", "", "Dharan", nil, "Butwal"].compact_blank
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
[1, "", nil, 2, " ", [], {}, false, true].compact_blank
# => [1, 2, true]
Here is a link to the docs and a link to the relative PR.
A destructive variant is also available. See Array#compact_blank!
.
If you have an older version of Rails
, check compact_blank
internal implementation.
It is not so complex to backport it.
def compact_blank
reject(&:blank?)
end
If you need to remove only nil
values, consider using Ruby build-in Array#compact
and Array#compact!
methods.
["a", nil, "b", nil, "c", nil].compact
# => ["a", "b", "c"]
Upvotes: 69
Reputation: 5861
To remove nil values do:
['a', nil, 'b'].compact ## o/p => ["a", "b"]
To remove empty strings:
['a', 'b', ''].select{ |a| !a.empty? } ## o/p => ["a", "b"]
To remove both nil and empty strings:
['a', nil, 'b', ''].select{ |a| a.present? } ## o/p => ["a", "b"]
Upvotes: 11
Reputation: 4242
Plain Ruby:
values = [1,2,3, " ", "", "", nil] - ["", " ", nil]
puts values # [1,2,3]
Upvotes: 0
Reputation: 63
another method:
> ["a","b","c","","","f","g"].keep_if{|some| some.present?}
=> ["a","b","c","f","g"]
Upvotes: 0
Reputation: 6707
Update with a strict with join
& split
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"]
cities.join(' ').split
Result will be:
["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Note that: this doesn't work with a city with spaces
Upvotes: -3
Reputation: 2581
Here is what works for me:
[1, "", 2, "hello", nil].reject(&:blank?)
output:
[1, 2, "hello"]
Upvotes: 118
Reputation: 62027
There are many ways to do this, one is reject
noEmptyCities = cities.reject { |c| c.empty? }
You can also use reject!
, which will modify cities
in place. It will either return cities
as its return value if it rejected something, or nil
if no rejections are made. That can be a gotcha if you're not careful (thanks to ninja08 for pointing this out in the comments).
Upvotes: 562
Reputation: 9075
Here is one more approach to achieve this
we can use presence
with select
cities = ["Kathmandu", "Pokhara", "", "Dharan", nil, "Butwal"]
cities.select(&:presence)
["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Upvotes: 10
Reputation: 11167
There are already a lot of answers but here is another approach if you're in the Rails world:
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].select &:present?
Upvotes: 12
Reputation: 1889
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)
=> ["A", "B", "C"]
Upvotes: 188
Reputation: 10631
Here is a solution if you have mixed types in your array:
[nil,"some string here","",4,3,2]
Solution:
[nil,"some string here","",4,3,2].compact.reject{|r| r.empty? if r.class == String}
Output:
=> ["some string here", 4, 3, 2]
Upvotes: 8
Reputation: 622
cities.reject! { |c| c.blank? }
The reason you want to use blank?
over empty?
is that blank recognizes nil, empty strings, and white space. For example:
cities = ["Kathmandu", "Pokhara", " ", nil, "", "Dharan", "Butwal"].reject { |c| c.blank? }
would still return:
["Kathmandu", "Pokhara", "Dharan", "Butwal"]
And calling empty?
on " "
will return false
, which you probably want to be true
.
Note: blank?
is only accessible through Rails, Ruby only supports empty?
.
Upvotes: 14
Reputation: 160551
Use reject
:
>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Upvotes: 20
Reputation: 49152
When I want to tidy up an array like this I use:
["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - ["", nil]
This will remove all blank or nil elements.
Upvotes: 46
Reputation: 400
Try this:
puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]
Upvotes: 23
Reputation: 981
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? }
Upvotes: 2