is there a way to know the index of the array element being processed by a block ?
I am trying to do something like this:
arr.any?{ |element|
# do some processing on the sub array [ element.index + 1 , end]
}
of course I can try and accomplish what I want using a for loop, but I was wondering if I can use blocks to do it, just to have a more ruby-ish code
You can make use of each_with_index and call it without block, so it returns Enumerator:
arr.each_with_index.any? do |el, index|
# your condition using index here
end
You can use
array.each_with_index { |item, index|
puts index
puts item
}
Related
I have data structure like List< HashMap< String, List>>:
records = [{"1"=>[{"account_id"=>"1", "v"=>"1"}, {"account_id"=>"1",
"v"=>"2"}, {"account_id"=>"1", "v"=>"3"}, {"account_id"=>"1",
"v"=>"4"]}, {"2"=>[{"account_id"=>"2", "v"=>"4"}, {"account_id"=>"2",
"v"=>"4"}, {"account_id"=>"2", "v"=>"4"}]}]
I don't care about the keys in hashmap ("1" and "2" in this case), and want to iterate values of map by group:
records.each do |account_map|
account_record = account_map.values[0] # This line
for i in (0 ... account_record.size - 1)
#do something and update account_record[i]
end
end
end
How can I merge account_record = account_map.values[0] into each loop or make it look better. Thanks
Your example is quite confusing, but the regular way to iterate a hash is the following
hash.each do |key, value|
end
So in your example it looks like you should do
records.each do |account_map|
account_map.each do |index, array|
array.each do |hash|
hash['account_id'] # This is how you access your data
hash['v'] # This is how you access your data
end
end
end
Of course you should use better variables names than index, array and hash.
Sometimes, I use Ruby's Enumerable#each_with_index instead of Array#each when I want to keep track of the index. Is there a method like Kernel#loop_with_index I could use instead of Kernel#loop?
loop without a block results in an Enumerator, which has a with_index method (and a each_with_index if you prefer that.)
loop.with_index{|_, i| puts i; break if i>100}
You could use Fixnum#upto with Float::INFINITY.
0.upto(Float::INFINITY) do |i|
puts "index: #{i}"
end
But, I'd probably just use Kernel#loop and keep track of the index myself because that seems simpler.
i = 0
loop do
puts "index: #{i}"
i += 1
end
So, yeah, I don't think there's anything like Kernel#loop_with_index.
In recent Ruby versions, Numeric#step has a default limit of Infinity and a step-size of 1.
0.step{|i| puts i ; break if i>100 }
1.I can't find an elegant way to write this code:
if array.empty?
# process empty array
else
array.each do |el|
# process el
end
end
I'd like to have one loop, without writing array twice. I read this, but there is no solution good enough.
2.
I am actually in an HAML template. Same question.
- if array.empty?
%p No result
- else
%ul
- array.each do |el|
%li el
What about?
array.each do |x|
#...
puts "x",x
end.empty? and begin
puts "empty!"
end
The cleanest way I've seen this done in HAML (not plain Ruby) is something like:
- array.each do |item|
%li
= item.name
- if array.empty?
%li.empty
Nothing here.
As mentioned by other answers, there is no need for the else clause because that's already implied in the other logic.
Even if you could do the each-else in one clean line, you wouldn't be able to achieve the markup you're trying to achieve (<p> if array.empty?, <ul> if array.present?). Besides, the HAML you show in your question is the best way to tell the story behind your code, which means it will be more readable and maintainable to other developers, so I don't know why you would want to refactor into something more cryptic.
I think there is no much more elegant or readable way to write this. Any way to somehow combine an iteration with a condition will just result in blackboxed code, meaning: the condition will just most likely be hidden in an Array extension.
If array is empty, then it will not be iterated, so the each block does not need to be conditioned. Since the return value of each is the receiver, you can put the each block within the empty? condition.
if (array.each do |el|
# process el
end).empty?
# process empty array
end
Assuming that "process empty array" leaves it empty after processing, you can leave out the else:
if array.empty?
# process empty array
end
array.each do |el|
# process el
end
or in one line:
array.empty? ? process_empty_array : array.each { |el| process_el }
An if the array is nil then we can enforce to empty array
if (array || []).each do |x|
#...
puts "x",x
end.empty?
puts "empty!"
end
I saw some people asking how to handle this for nil cases.
The trick is to convert it to string. All nils converted to string becomes a empty string, all empty cases continue being empty.
nil.to_s.empty?
"".to_s.empty?
both will return true
I am trying to style the first element output through an object.each do |x| command by applying an .active class. I cannot figure it out though - how would I do that?
Use each_with_index(). Shown below in a non-ERB example for clarity.
['hello', 'world'].each_with_index do |item, index|
if index == 0
puts "This is the first item"
end
puts item
end
Prints out:
This is the first item
hello
world
It seems very obvious:
objects.first.css_options += ' .active'
And then iterate through all objects in usual manner.
In case of variation can be different, for example you want also apply css option to last element:
objects.zip(['active','','',...]).each do |obj,klass|
obj.css_option += klass
...
end
[obj1, obj2].each_with_index do |item, index|
item.css_option += ' .active' if index == 0
end
When moving over an iteration such as:
array.each do |row|
puts "Current row count: " + row.current_row_index
# do some more stuff
end
Is there a way to get the index of the current iteration / row? Obviously I can just throw in a counter, but I'm curious if there's a shortcut for an index function that shows it's current position.
Been digging through the available methods via pry, however I've not seen anything that seems to do this out of the box.
array.each_with_index |row, index|
puts index
end
If you need exactly the index
array.each_index do |index|
puts index
end