How to remove the tailing nil/empty values in array - ruby

How to remove the tailing nil/empty values in array?
I want to remove the tailing nil values in the following array,
So the array size may become 125, not 127
...
[123] "Conc_Net_LE_8_TDR_Long_Other",
[124] "Conc_Net_LE_8_TDR_Short_Other",
[125] "Contract_Units",
[126] nil,
[127] nil,

["foo", nil, ""].grep(/./)
# => ["foo"]

You can do
new_array = array.compact.delete("")
#compact will remove all nil objects, and using #delete, you can delete all empty string object(""). You can also do :
array.delete_if { |elem| elem.nil? || elem.empty? }

Use Array#compact, or the bang version compact! to modify the called object to remove the nil elements.
> arr = [1, nil]
> arr.compact
=> [1]
To remove nil and empty you can use Array#reject or also the bang version reject!
arr = [1, nil, ""]
arr.reject { |i| i.to_s.empty? }
=> [1]

If you are interested to remove only the tailing nil and empty sequence, maybe you can do something like this
array = ["1","2","3",nil," ","4",nil,nil, ""]
rev = array.reverse
while rev[0] == nil or is_empty_sequence?(rev[0])
rev.shift
end
p rev.reverse #Output -> ["1","2","3",nil," ","4"]
where is_empty_sequence? is a method where you declared what are the empty sequence.

Related

Ruby hash: return the first key value under which is not nil

Say I have a hash
hash = {a:1, b:false, c:nil}
& a series of keys somewhere: [:c, :b, :a]. Is there a Ruby idiom for returning such a key value under which != nil?
The obv
[:c, :b, :a].select {|key| hash[key] != nil}.first # returns :b
seems too long.
For that I think Enumerable#find might work:
find(ifnone = nil) { |obj| block } → obj or nil
find(ifnone = nil) → an_enumerator
Passes each entry in enum to block. Returns the first for which block
is not false. If no object matches, calls ifnone and returns its
result when it is specified, or returns nil otherwise.
If no block is given, an enumerator is returned instead.
In your case it'd return the first for which block is not nil:
p %i[c b a].find { |key| !{ a: 1, b: nil, c: nil }[key].nil? } # :a
p %i[c b a].find { |key| !{ a: 1, b: 1, c: nil }[key].nil? } # :b
If you want to filter elements with falsy values, you can use the following expressions.
keys = [:d, :c, :b, :a]
hash = { a: 1, b: nil, c: nil, d: 2 }
keys.select(&hash)
# => [:d, :a]
If you want to filter elements with exactly nil as a value, it is not correct, as Mr. Ilya wrote.
You can use detect this will return first value if match.
[:c, :b, :a].detect { |key| hash[key] != nill }. This will return :b.
Hope to help you :D

How to check if a key exists in an array of arrays?

Is there a straightforward way to do something like the following without excessive looping?
myArray = [["a","b"],["c","d"],["e","f"]]
if myArray.includes?("c")
...
I know this works fine if it's just a normal array of chars... but I would like something equally as elegant for an array of an array of chars (bonus points for helping convert this to an array of tuples).
If you only need a true/false answer you can flatten the array and call include on that:
>> myArray.flatten.include?("c")
=> true
You can use assoc:
my_array = [['a', 'b'], ['c', 'd'], ['e', 'f']]
if my_array.assoc('c')
# ...
It actually returns the whole subarray:
my_array.assoc('c') #=> ["c", "d"]
or nil if there is no match:
my_array.assoc('g') #=> nil
There's also rassoc to search for the second element:
my_array.rassoc('d') #=> ["c", "d"]
my_array = [["a","b"],["c","d"],["e","f"]]
p my_hash = my_array.to_h # => {"a"=>"b", "c"=>"d", "e"=>"f"}
p my_hash.key?("c") # => true
You can use Array#any?
myArray = [["a","b"],["c","d"],["e","f"]]
if myArray.any? { |x| x.includes?("c") }
# some code here
The find_index method works well for this:
myArray = [["a","b"],["c","d"],["e","f"]]
puts "found!" if myArray.find_index {|a| a[0] == "c" }
The return value is the array index of the pair or nil if the pair is not found.
You can capture the pair's value (or nil if not found) this way:
myArray.find_index {|a| a[0] == "c" } || [nil, nil])[1]
# => "d"

Replace Empty Cells in Array With Nil in Ruby?

I have a two-dimensional array of a bunch of strings, including some empty strings. I want to replace the empty strings with nil. How do I do this in Ruby?
Sample array:
[['cat','','dog',''],['','','fish','','horse']]
Desired output:
[['cat',nil,'dog',nil],[nil,nil,'fish',nil,'horse']]
[['cat','','dog',''],['','','fish','','horse']].map do |arr|
arr.map { |s| s unless s.empty? }
end
# => [["cat", nil, "dog", nil], [nil, nil, "fish", nil, "horse"]]

How to find a hash key containing a matching value

Given I have the below clients hash, is there a quick ruby way (without having to write a multi-line script) to obtain the key given I want to match the client_id? E.g. How to get the key for client_id == "2180"?
clients = {
"yellow"=>{"client_id"=>"2178"},
"orange"=>{"client_id"=>"2180"},
"red"=>{"client_id"=>"2179"},
"blue"=>{"client_id"=>"2181"}
}
Ruby 1.9 and greater:
hash.key(value) => key
Ruby 1.8:
You could use hash.index
hsh.index(value) => key
Returns the key for a given value. If
not found, returns nil.
h = { "a" => 100, "b" => 200 }
h.index(200) #=> "b"
h.index(999) #=> nil
So to get "orange", you could just use:
clients.key({"client_id" => "2180"})
You could use Enumerable#select:
clients.select{|key, hash| hash["client_id"] == "2180" }
#=> [["orange", {"client_id"=>"2180"}]]
Note that the result will be an array of all the matching values, where each is an array of the key and value.
You can invert the hash. clients.invert["client_id"=>"2180"] returns "orange"
You could use hashname.key(valuename)
Or, an inversion may be in order. new_hash = hashname.invert will give you a new_hash that lets you do things more traditionally.
try this:
clients.find{|key,value| value["client_id"] == "2178"}.first
According to ruby doc http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-key key(value) is the method to find the key on the base of value.
ROLE = {"customer" => 1, "designer" => 2, "admin" => 100}
ROLE.key(2)
it will return the "designer".
From the docs:
(Object?) detect(ifnone = nil) {|obj| ... }
(Object?) find(ifnone = nil) {|obj| ... }
(Object) detect(ifnone = nil)
(Object) find(ifnone = nil)
Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.
If no block is given, an enumerator is returned instead.
(1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35
This worked for me:
clients.detect{|client| client.last['client_id'] == '2180' } #=> ["orange", {"client_id"=>"2180"}]
clients.detect{|client| client.last['client_id'] == '999999' } #=> nil
See:
http://rubydoc.info/stdlib/core/1.9.2/Enumerable#find-instance_method
The best way to find the key for a particular value is to use key method that is available for a hash....
gender = {"MALE" => 1, "FEMALE" => 2}
gender.key(1) #=> MALE
I hope it solves your problem...
Another approach I would try is by using #map
clients.map{ |key, _| key if clients[key] == {"client_id"=>"2180"} }.compact
#=> ["orange"]
This will return all occurences of given value. The underscore means that we don't need key's value to be carried around so that way it's not being assigned to a variable. The array will contain nils if the values doesn't match - that's why I put #compact at the end.
Heres an easy way to do find the keys of a given value:
clients = {
"yellow"=>{"client_id"=>"2178"},
"orange"=>{"client_id"=>"2180"},
"red"=>{"client_id"=>"2179"},
"blue"=>{"client_id"=>"2181"}
}
p clients.rassoc("client_id"=>"2180")
...and to find the value of a given key:
p clients.assoc("orange")
it will give you the key-value pair.

Add nil object as an element of an array in Ruby

Can I have an array which has nil as a value in it?, e.g., [1, 3, nil, 23].
I have an array in which I assign nil like this array = nil, and then I want to iterate through it but I can't. The .each method fails saying nil class.
Is it possible to do this?
Use:
a = [nil]
Example:
> a = nil
=> nil
> a.each{|x|puts x}
NoMethodError: undefined method `each' for nil:NilClass
from (irb):3
from :0
> a= [nil]
=> [nil]
> a.each{|x|puts x}
nil
=> [nil]
I believe your problem lies in when you "assign nil" to the array
arr = []
arr = nil
Is this something like what you tried doing? In this case you do not assign nil to the array you assign nil to the variable arr, hence arr is now nil giving you errors concerning a "nil class"
Sure you can. You are probably trying to do something with the nil object without checking to see if it's nil? first.
C:\work>irb
irb(main):001:0> a = [1,2,nil,3]
=> [1, 2, nil, 3]
irb(main):003:0> a.each{|i|
irb(main):004:1* if i.nil? then
irb(main):005:2* puts ">NADA>"
irb(main):006:2> else
irb(main):007:2* puts i
irb(main):008:2> end
irb(main):009:1> }
1
2
>NADA>
3
=> [1, 2, nil, 3]
irb(main):010:0>
I think you're confusing adding an item to an array with assigning a value of nil to a variable.
Add an item to (the end of) an array (two ways):
array.push(item)
# or if you prefer
array << item
# works great with nil, too
array << nil
I'm assuming that the array already exists. If it doesn't, you can create it with array = [] or array = Array.new.
On the other hand, array = nil assigns nil to a variable that happens to be (misleadingly) named 'array'. If that variable previously pointed to an array, that connection is now broken.
You may be thinking of assignment with an index position, but array[4] = nil is very different from array = nil.
There is a problem with how you're storing the nil value in the array. Here is an example to show how arrays work:
a = nil
b = [nil]
c = []
c.push(nil)
# a is nil
# b is [nil]
# c is now [nil]
So, 'b' and 'c' both created an array with a nil attribute while 'a' just set a variable to nil (NOT an array).
With either 'b' or 'c', you should now be able to run .each without any problem
use Enumerable#map
ruby-1.8.7-p249 > [1,2,nil,4].map{|item| puts item}
1
2
nil
4
=> [nil, nil, nil, nil]
note that even though the return is nil for each item in the array, the original array is as it was. if you do something to operate on each item in the array, it will return the value of each operation. you can get rid of nils buy compacting it.
ruby-1.8.7-p249 > [1,2,nil,4].map{|item| item + 1 unless item.nil? }
=> [2, 3, nil, 5]
ruby-1.8.7-p249 > [1,2,nil,4].map{|item| item + 1 unless item.nil? }.compact
=> [2, 3, 5]

Resources