Return value of iteration over array - arrays

I'm trying to build a music library.
My main problem is when I iterate over the array with the #each method the return value is huge knowing that my array is all the albums and songs about one artist.
Would you know a way to iterate over arrays with a return value of nil or at least way shorter than the entire artist array I created?

Just return nil after the iteration if you don't want the collection as a return value.
def your_method
your_collection.each do |item|
# do something
end
nil
end

Compact method will eliminate nil values, if that is what you mean.
['foo', nil, 'bar'].compact.each do |part|
puts part
end
=> foo
bar

Add a && nil after your expression:
myarray.each {....} && nil

Related

Ruby - elegantly flatten an array but don't ignore empty sub-arrays

Using .flatten is a handy little trick to take an array of sub-arrays and turn it into a single array.
For example: [[1,3],2,[5,8]].flatten => [1,3,2,5,8]
You can even include nil [1,[2,nil],3].flatten will result in [1,2,nil,3].
This kind of method is very useful when nesting a .map method, but how would you account for an empty sub-array? For example: [1,[2,3],[],4].flatten would return [1,2,3,4]... but what if I need to keep track of the empty sub array maybe turn the result into [1,2,3,0,4] or [1,2,3,nil,4]
Is there any elegant way to do this? Or would I need to write some method to iterate through each individual sub-array and check it one by one?
If you don't need to recursively check nested sub-arrays:
[1,[2,3],[],4].map { |a| a == [] ? nil : a }.flatten
First map the empty arrays into nils, then flatten
[1,2,[1,2,3],[]].map{|x| if x.is_a? Array and x.empty? then nil else x end}.flatten

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 to map only non-empty values?

I am building an iOS app and I got an array with textfields and I want to map the text of these fields into an array.
This is what I try and it works but I only want to map a value if it is not empty. Now I get all even if the textfield is empty.
textFields.map{$0.text!}
Update
I solved it like this
textFields.filter({$0.text! != ""}).map({$0.text!})
The current answers both involve two passes through arrays: one to filter, and one to map.
A more efficient approach would be:
textFields.flatMap{ $0.text?.isEmpty == false ? $0.text! : nil }
The closure { $0.text?.isEmpty == false ? $0.text! : nil } returns the text property of each element if it is non-nil (since it is an optional property) and it is not empty (empty means == ""). Otherwise, it will return nil.
Because the flatMap method will already exclude any nil values from the final result, this guarantees that the return will be only the array of non-nil, non-empty text strings from the original elements, and does so with only a single pass through the array.
textFields.flatMap({ $0.text }).filter({ !$0.isEmpty })
Or, if you want to avoid flatMap:
textFields.map({ $0.text }).filter({ !($0?.isEmpty ?? true) })
This is how I would do it:
textFields.flatMap{
guard let t = $0.text, !t.isEmpty else { return nil }
return t
}
As Daniel Hall answer, you should avoid 2 passes.
Before Swift 4 you need to use flatMap as he said.
But now you need to use compactMap so:
let array = [1, 2, nil, 4, nil, 6]
let cleanArray = array.compactMap { $0 * 1 }
This runs 6 times (1 for each value) but the result only have 4 values.
More info here:
https://medium.com/#abhimuralidharan/higher-order-functions-in-swift-filter-map-reduce-flatmap-1837646a63e8
I solved it like this:
textFields.filter({$0.text! != ""}).map({$0.text!})
For filtering the non empty values, WE Can go for FILTER in SWIFT 3.
filter({$0.text! != ""})
you don't need to go for MAP function.
This will give you only non empty (!="") values.
Thanks.

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 }

Lua doesn't go over 'nil' in table

I have such an anonymous Lua function:
an_func = function(x) return x == nil end
I need to test it on a table from 4 values: {'None', nil, 1, '1'}.
So, I wrote the following code:
for num, element in pairs({'None', nil, 1, '1'}) do
print(num .. ': ' .. tostring(an_func(element)))
end
When I ran it, I got only three lines:
1: false
3: false
4: false
The line with the true value (corresponding to nil table element) didn't print.
Can you explain, why did Lua print all results, but true? How can I fix the snipped make it output all 4 lines?
P.S. I'm newbee in Lua.
When using pairs(), it goes over all elements of a table. nil means nothing, so it won't go over it. Why should it tell you there's nothing in the table? If you have a totally new table, it'll return nil if you index it with anything. print(({}).test) --> nil
If you really want to get the nil, you could use a dummy value:
local NIL = setmetatable({},{__tostring=function() return "nil" end})
an_func = function(x) return x == NIL end
for num, element in pairs({'None', NIL, 1, '1'}) do
print(num .. ': ' .. tostring(an_func(element)))
end
Output:
1: false
2: true
3: false
4: false
In Lua, everything (a function, string, thread, ...) is a value, with nil (and technically none/void) being the only exception(s). To put simply, nil represents the absence of value. So when iterating over a table, why would Lua say there is nothing there. If it did it would have to iterate over every virtually possible index you can create.
However it appears you are using an array. You technically can iterate over it assuming you know the length. I'll make the assumption that the last item in the table is NOT nil, and that there wasn't any holes assigned after the initial length of the table with holes, however this may not necessarily be true in your case, if it isn't you will have to keep track of the length yourself and use it rather than the # operator:
for i = 1,#t do
local v = t[i]
print (v == nil)
end
Other answers address your second question well but the simple explanatory facts are Any key with value nil is not considered part of the table. Conversely, any key that is not part of a table has an associated value nil. Assigning a value of nil removes any existing key-value pair with the same key.
You would need to loop through all keys you want to print the values for.
Possible ways:
Know the length beforehand. (warspyking noted about this)
Using an end marker.
Calculate the length somehow (for example with maxn).
Use something to represent nil values. (EinsteinK showed an example
of this)
Each has their good and bad sides, here are some:
For the first you would need to know the length beforehand in all cases which may be difficult.
The end marker is convenient, but requires you to shift around the end marker.
Calculating length would not work if the last element is nil.
Example of calculating the length - assuming last element is not nil.
Note that lua 5.1 has table.maxn that you can use instead of this custom implementation of maxn.
an_func = function(x) return x == nil end
function maxn(t)
local n = 0
for k,v in pairs(t) do
if k%1 == 0 then
n = k
end
end
return n
end
local t = {'None', nil, 1, '1'}
for num = 1, maxn(t) do
print(num .. ': ' .. tostring(an_func(t[num])))
end
Example of using an end marker:
an_func = function(x) return x == nil end
local END = {}
local t = {'None', nil, 1, '1', END}
local num = 1
while t[num] ~= END do
print(num .. ': ' .. tostring(an_func(t[num])))
num = num+1
end

Resources