开发者

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?

How do I remove blank elements from an array?


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜