Python list comprehension => Ruby select / reject on index rather than element

Viewed 1180

Given:

arr=[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
      0   1   2   3   4   5   6   7   8    9    # index of arr

In Python, one can select or reject elements of a list given the index of that element by combining enumerate and an if clause in a list comprehension:

Every item except the third:

>>> [e for i,e in enumerate(arr) if i%3]
[20, 30, 50, 60, 80, 90]

Every third item in a list:

>>> [e for i,e in enumerate(arr) if not i%3]
[10, 40, 70, 100]

Or, even easier, with a slice:

>>> arr[::3]
[10, 40, 70, 100]   

In Ruby, we have .select and .reject

> arr.each_with_index.reject { |e,i| i%3==0 }
=> [[20, 1], [30, 2], [50, 4], [60, 5], [80, 7], [90, 8]]
> arr.each_with_index.select { |e,i| i%3==0 }
=> [[10, 0], [40, 3], [70, 6], [100, 9]]

And then apply .collect to that:

> arr.each_with_index.select { |e,i| i%3==0 }.collect{|e,i| e}
=> [10, 40, 70, 100]

For the slice, the rough Ruby equivalent might be:

> (0..arr.length).step(3).each { |e| p arr[e] }
10
40
70
100
=> 0..10

But I can't figure out how toe collect those into a new array other than:

> new_arr=[]
=> []
> (0..arr.length).step(3).each { |e| new_arr.push(arr[e]) }
=> 0..10
> new_arr
=> [10, 40, 70, 100]

Questions:

  1. Are these the best Ruby idioms for what I am trying to do (.select or .reject with .collect)?
  2. Is there a way to do something along these lines with a slice:
    new_arr=(0..arr.length).step(3).each { |e| arr[e] }.some_method?
3 Answers
Related