How do I remove blank elements from an array?
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", "Butw开发者_StackOverflowal"]
Is there any method like compact
that will do it without loops?
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).
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)
=> ["A", "B", "C"]
Here is what works for me:
[1, "", 2, "hello", nil].reject(&:blank?)
output:
[1, 2, "hello"]
In my project I use delete
:
cities.delete("")
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.
compact_blank (Rails 6.1+)
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"]
Most Explicit
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"]
Try this:
puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]
Use reject
:
>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
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?
.
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?
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"]
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"]
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]
You can Try this
cities.reject!(&:empty?)
cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? }
Shortest way cities.select(&:present?)
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?
another method:
> ["a","b","c","","","f","g"].keep_if{|some| some.present?}
=> ["a","b","c","f","g"]
Plain Ruby:
values = [1,2,3, " ", "", "", nil] - ["", " ", nil]
puts values # [1,2,3]
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
精彩评论