How to remove array elements where element's fields are NULL - arrays

array = [[1555,100],[nil,95],[1774,nil],[1889,255]]
What would be the best way to remove the 2nd and 3rd elements from array since they have NULL fields?
Expected output :
array = [[1555,100],[1889,255]]

arr = [[1555,100],[nil,95],[1774,nil],[1889,255]]
arr.reject { |a,b| (a && b).nil? }
#=> [[1555, 100], [1889, 255]]

And yet another option:
array.reject { |a| a.any?(&:nil?) }
It is very similar to Cary Swoveland's answer, but will work with arrays of any length and will remove [false, nil] as well.

Use .compact to remove nil elements from array of arrays
array.map(&:compact)
# array = [[1555,100], [95], [1774], [1889, 255]]
Edit
Use .reject! to remove sub arrays containing nil elements.
array.reject! { |e| e.any? nil }
# array = [[1555,100], [1889,255]]

Related

array.nil? when array having only multiple `nil` values

Consider an array having only one value nil
array = [nil]
Is there any better way to check whether an array is nil or not, like array.nil??
This works:
array == [nil]
But what if there are multiple nil values in the array?
array = [nil, nil, nil]
Below is the requirement:
array = [1, 2] if array.nil?
array.nil? should also give 'true' when array = [nil, nil, nil]
You can use Array#any? to check if the array contains at least one value that is not false or nil:
array = [1,2] unless array.any?
If array is allowed to contain false and you are interested only in nil then Array#any? needs a block:
array = [1,2] unless array.any?{|i| !i.nil?}
Update
As #mu-is-too-short suggests, a better version is:
array = [1,2] if array.all?(&:nil?)
It does exactly what you need: Enumerable#all? returns true if the block returns a true-ish value for all elements of the array.
One option is to uniquify your array and then do what you were already doing:
array.uniq == [nil]
So if array is any amount of nils it will be true. On the other hand:
array.nil?
Checks whether array itself is nil, which is not the same as an array containing nil elements.
One of possible ways is to remove nil values with .compact and check if the result is empty? .
array = [1, 2] if array.compact.empty?

How do I strip off nil elements from the end of an array if all my elements are nil?

I'm using Ruby 2.4. I want to strip off nil elements from the end of an array, so I'm using
row_data.pop until row_data.last
but if the array only contains nil elements, this seems to cause some kind of infinite loop because the call never returns. How do I account for the fact that the array might contain all nil elements?
Just add an extra check to see if the array is empty.
row_data.pop until row_data.last || row_data.empty?
You can use Array#rindex to obtain the right-most non-nil entry (or determine that every element in the array is nil).
def kill_nils_at_end(arr)
ndx = arr.rindex(&:itself)
ndx ? arr[0..ndx] : []
end
kill_nils_at_end [1,nil,1,nil,nil,nil]
#=> [1, nil, 1]
kill_nils_at_end [nil,nil,nil,nil,nil,nil]
#=> []
This does not mutate the original array. If you wish to modify the array in place, change the penultimate line to
arr.replace(ndx ? arr[0..ndx] : [])
Try this
Most readable
arr = arr.reverse.drop_while(&:nil?).reverse
Most efficient
arr.slice!(0..arr.rindex { |each| nil != each }.to_i)
If all nils are to be removed, try this:
[1, nil, 3, nil, nil].compact #= [1,3]
see Map and Remove nil values in Ruby

How do I apply my function to non-nil elements only?

I’m using Rails 4.2.7. I have this concise function that trims (strips) strings in my array
data_cols = data_cols.collect{|x| x.strip || x }
However if one of the elements in the array is nil, the above falls apart. How can I modify the above so that it won’t apply to nil elements?
If you want to remove nil values from the array entirely, you can use compact:
cols.compact.map { |col| col.strip }
# or
cols.compact.map(&:strip)
If you want to keep all values, but only operate on the non-nil values, you can simply use a nil-guard:
# straightforward, no magic, works across rubies:
cols.map { |col| col && col.strip }
# a wee dose of magic in ruby 2.3 (safe navigation operator)
cols.map { |col| col&.strip }
Finally, if you want to be more idiomatic and ruby-esque, you can use duck-typing and let the objects sort out themselves whether or not they can be "strip'ped":
cols.map { |col| col.respond_to?(:strip) ? col.strip : col }
you can use try
data_cols = data_cols.collect{|x| x.try(:strip) }
http://apidock.com/rails/Object/try
Depends if you still want the nil values in your result array. If not, you can just use compact:
data_cols = data_cols.compact.collect{|x| x.strip || x }
compact will remove all the nil values in the array.
If you want to keep nil values, you need to change your condition:
data_cols = data_cols.compact.collect{|x| x ? x.strip : nil }

How can i get the value from array without using regex in ruby?

From the array of string I need to get string which starts with age- followed by maximum of 2 digit number and optional '+' sign.
Ex: age-1, age-22, age55, age-1+, age-15+
Following is my array:
arr = ["vintage-colllections","age-5"]
or
arr = ["vintage-colllections","age-51+"]
I will extract age "age-5" or "age-51+" from the array.
I tried following things:
arr.find {|e| e.include?"age-"}
Works well for other scenarios but in above the 1st element of array also includes (vint)age- failing there.
arr.find { |e| /age-\d*\+?/ =~ e}
Works fine but I am trying to avoid regex.
Is there any other better approach ?.
Any suggestions are welcome.
Use start_with?:
arr.find { |e| e.start_with?("age-") }
I must grit my teeth to not use a regex, but here goes. I assume the question is as described in a comment I left on the question.
def find_str(arr)
arr.map { |str| str_match(str) }.compact
end
def str_match(str)
return nil unless str[0,4] == "age-"
last = str[-1] == '+' ? -2 : -1
Integer(str[4..last]) rescue return nil
str
end
find_str ["cat", "age-5"] #=> ["age-5"]
find_str ["cat", "age-51+"] #=> ["age-51+"]
find_str ["cat", "age-5t1+"] #=> []
find_str ["cat", "xage-51+"] #=> []

In Ruby, how do I return all the index value of elements in an array that have the same string values in them?

How do I return all the index value of elements in an array that have the same string values in them?
For example:
myarray=[tree, bean, bean, bunny, frog, bean, soup]
If I searched for "bean" using something myarray.index(bean) it would return 1. If I did the same search using myarray.rindex(bean) it would return 5.
I need the method to myarray.{does this method exist?}(bean) that would return [1, 2, 5].
Any suggestions?
You can use #each_with_index (create pair of string, index), then #map (iterate over the pairs and if it matches, then return index, otherwise return nil) and finally #compact (remove nil values) the array.
myarray.each_with_index.map{|x,i| x == "bean"? i : nil}.compact
Slightly simpler soulution and a better one also in terms of efficiency would be probably this one with #each_index.
myarray.each_index.select{|x| myarray[x] == "bean"}
Btw. you should name the variable my_array, not myarray.
Simple & easy to understand solution given below
myarray = [:tree, :bean, :bean, :bunny, :frog, :bean, :soup]
result = []
search_for = :bean
myarray.each_with_index() { |element, index| result << index if element == search_for }
p result
Output
[1, 2, 5]

Resources