Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby find next in array

Tags:

arrays

ruby

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
like image 396
dennismonsewicz Avatar asked Jan 04 '11 17:01

dennismonsewicz


People also ask

How to find index of an element in an array in Ruby?

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.

What is slice in Ruby?

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.

How do you find the value of an array?

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() .


5 Answers

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?
   ...

}
like image 60
Jacob Relkin Avatar answered Oct 11 '22 09:10

Jacob Relkin


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.

like image 22
Marc-André Lafortune Avatar answered Oct 11 '22 11:10

Marc-André Lafortune


arr[n..-1].find_index(obj) + n
like image 42
wilhelmtell Avatar answered Oct 11 '22 10:10

wilhelmtell


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"
like image 4
Alexander Presber Avatar answered Oct 11 '22 11:10

Alexander Presber


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.

like image 4
Eskim0 Avatar answered Oct 11 '22 09:10

Eskim0