Is there anyway to find the next item in a Ruby Array?
Code:
# Find ALL languages
if !debug
lang = Language.all
else
lang = Language.where("id = ? OR id = ?", 22, 32)
end
# Get all elements
elements = Element.where("human_readable IS NOT NULL")
lang.each do |l|
code = l.code.downcase
if File.exists?(file_path + code + ".yml")
File.delete(file_path + code + ".yml")
end
t1 = Time.now
info = {}
elements.each do |el|
unless l.id == 1
et = el.element_translations.where("language_id = ? AND complete = ?", l.id, true)
else
et = el.element_translations.where("language_id = ?", 1)
end
et.each do |tran|
info[code] ||= {}
info[code][el.human_readable] = tran.content.gsub("\n", "").force_encoding("UTF-8").encode!
end
end
File.open(file_path + code + ".yml", "w", :encoding => "UTF-8") do |f|
if f.write(info.to_yaml)
t2 = Time.now
puts code + ".yml File written"
puts "It took " + time_diff_milli(t1, t2).to_s + " seconds to complete"
# This is where I want to display the next item in the lang array
puts lang.shift(1).inspect
puts "*"*50
end
end
end
Ruby | Array class find_index() operation Array#find_index() : find_index() is a Array class method which returns the index of the first array. If a block is given instead of an argument, returns the index of the first object for which the block returns true.
slice() is a method in Ruby that is used to return a sub-array of an array. It does this either by giving the index of the element or by providing the index position and the range of elements to return.
If you need to find the index of a value, use Array.prototype.indexOf() . (It's similar to findIndex() , but checks each element for equality with the value instead of using a testing function.) If you need to find if a value exists in an array, use Array.prototype.includes() .
Array
includes Enumerable
, so you can use each_with_index
:
elements.each_with_index {|element, index|
next_element = elements[index+1]
do_something unless next_element.nil?
...
}
A nice way to iterate over an Enumerable
if you need to access both an element and the next one is using each_cons
:
arr = [1, 2, 3]
arr.each_cons(2) do |element, next_element|
p "#{element} is followed by #{next_element}"
#...
end
# => "1 is followed by 2", "2 is followed by 3".
As pointed out by Phrogz, Enumerable#each_cons
is available in Ruby 1.8.7+; for Ruby 1.8.6 you can require 'backports/1.8.7/enumerable/each_cons'
.
As @Jacob points out, the other approach is to use each_with_index
.
arr[n..-1].find_index(obj) + n
Based on Marc-Andrés nice answer I want to provide an answer that, in a generic way, gives the following element for all elements, also the last one, by padding with nil
:
arr = [1, 2, 3]
[arr, nil].flatten.each_cons(2) do |element, next_element|
p "#{element} is followed by #{next_element || 'nil'}"
end
# "1 is followed by 2"
# "2 is followed by 3"
# "3 is followed by nil"
Now, while we are at it, we can also provide the preceding element for all elements:
arr = [1, 2, 3]
[nil, arr, nil].flatten.each_cons(3) do |prev_element, element, next_element|
p "#{element} is preceded by #{prev_element || 'nil'} and followed by #{next_element || 'nil'}"
end
# "1 is preceded by nil and followed by 2"
# "2 is preceded by 1 and followed by 3"
# "3 is preceded by 2 and followed by nil"
or add this to your project, then you can call the next_item(item)
method on whatever array you like.
class Array
def next_item(item)
self[self.find_index(item) + 1] unless self.find_index(item).nil?
end
end
note on the use of self
in my proposed answer. I recognize that the use self
is, in one sense, redundant and unnecessary. It is my preference to use self
more frequently than needed to make the code more obvious, especially to junior programmers. Simplicity, even when it requires more characters, is important to me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With