Return iterating object and index on repeat

array = [1,2,3,{:name => "Peter"}, "hello"] array.each do |element| # it can be "inject", "map" or other iterators # How to return object "array" and position of "element" # also next and priviouse "element" end 

Of course, I can return the index of array.index[element] , but I'm looking for a more natural solution. Like proxy_owner in Rails associations

Ruby 1.8.7

What do I want to withdraw? I want to return the object that I iterate (array in my case), also the number of iterations (index in the case of each_with_index) and the priviouse iteration element.

As input, I have an array and an iterator (each, map, insert, etc.)

+4
source share
5 answers

Use Enumerable#each_cons . Below is a copy of ruby1.8.7 rdoc . It should work on ruby ​​1.8.7.


  • each_cons (n) {...}
  • each_cons (n)

Iterates this block for each array of consecutive elements. If none of the blocks is specified, an enumerator is returned.


With this, you can give an array:

 ['a', 'b', 'c', 'd', 'e'].each_cons(3).to_a # => ["a", "b", "c"], ["b", "c", "d"], ["c", "d", "e"]] 

or do:

 ['a', 'b', 'c', 'd', 'e'].each_cons(3) {|previous, current, nekst| puts "#{previous} - #{current} - #{nekst}" } # => a - b - c # => b - c - d # => c - d - e 

If you want to index,

 ['a', 'b', 'c', 'd', 'e'].each_cons(3).to_a.each_with_index {|(previous, current, nekst), i| puts "#{i + 1}. #{previous} - #{current} - #{nekst}" } # => 1. a - b - c # => 2. b - c - d # => 3. c - d - e 

You can pass an array to other enums, usually with inject :

 ['a', 'b', 'c', 'd', 'e'].each_cons(3).to_a.inject(''){|str, (previous, current, nekst)| str << previous+current+nekst } # => "abcbcdcde" 
+6
source

There is each_with_index .

If you want other iterators, such as inject , map , ..., and if you use ruby1.9, there is an Enumerator#with_index method that you can attach to various iterators.

Enumerator # with_index

+5
source

The Ruby function each_with_index can be easily recreated:

 ary = %w[zero one two three] ary.zip((0 .. (ary.size - 1)).to_a).to_a # => [["zero", 0], ["one", 1], ["two", 2], ["three", 3]] ary.zip((0 .. (ary.size - 1)).to_a).each do |a, i| puts "this element: #{a}" puts "previous element: #{ary[i - 1]}" if (i > 0) puts "next element: #{ary[i + 1]}" if (i < (ary.size - 1)) puts end # >> this element: zero # >> next element: one # >> # >> this element: one # >> previous element: zero # >> next element: two # >> # >> this element: two # >> previous element: one # >> next element: three # >> # >> this element: three # >> previous element: two # >> 

Once you find out the index for the current object, you can look into the array you are repeating and easily get the previous and next values.

So you can do:

 module Enumerable def my_each_with_index self.zip((0 .. (self.size - 1)).to_a).each do |a, i| yield a, i end end end ary.my_each_with_index { |a,i| puts "index: #{i} element: #{a}" } # >> index: 0 element: zero # >> index: 1 element: one # >> index: 2 element: two # >> index: 3 element: three 
+3
source

Cannot check, but if correctly remembered:

 a = [4, 3, 3, 1, 6, 6,1] p a.enum_for(:each_with_index).inject([]){ |m,args| m<<args } #=> [[4, 0], [3, 1], [3, 2], [1, 3], [6, 4], [6, 5], [1, 6]] 

Replace injection with select, reject, or whatever. With Ruby 1.9:

 p a.each_with_index.inject([]){ |m,args| m<<args } 
+1
source

Edit: this is for 1.9, I have now seen that your question explicitly mentions 1.8.7. I will leave it here for reference, but if it bothers anyone, I can delete it.

Saw already indicated Enumerator#with_index :

http://www.ruby-doc.org/core/classes/Enumerator.html#M000303

Examples:

 >> [1,2,3].map.with_index { |x, i| [x,i] } => [[1, 0], [2, 1], [3, 2]] >> [1,2,3].each_cons(2).with_index { |(x, y), i| p [x,y,i] } [1, 2, 0] [2, 3, 1] => nil 

Also related to this issue are Enumerator#next and Enumerator#peek , which will return the next object in the enumerator, respectively, without moving the internal position forward.

http://www.ruby-doc.org/core/classes/Enumerator.html#M000307

http://www.ruby-doc.org/core/classes/Enumerator.html#M000308

+1
source

Source: https://habr.com/ru/post/1345371/


All Articles