Python list comprehension => Ruby选择/拒绝索引而不是元素

daw*_*awg 4 ruby arrays

鉴于:

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

在Python中,通过组合enumerateif列表理解中的子句,可以选择或拒绝给定该元素索引的列表元素:

除第三项外的所有项目:

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

列表中的每三个项目:

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

或者,更简单,有一个切片:

>>> arr[::3]
[10, 40, 70, 100]   
Run Code Online (Sandbox Code Playgroud)

在Ruby中,我们有.select.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]]
Run Code Online (Sandbox Code Playgroud)

然后将.collect应用于:

> arr.each_with_index.select { |e,i| i%3==0 }.collect{|e,i| e}
=> [10, 40, 70, 100]
Run Code Online (Sandbox Code Playgroud)

对于切片,粗略的 Ruby等价物可能是:

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

但我无法弄清楚如何将这些收集到一个新的阵列中除了:

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

问题:

  1. 这些是我尝试做的最好的Ruby习语(.select或.reject with .collect)?
  2. 有没有办法沿着这些线做一些切片:
    new_arr=(0..arr.length).step(3).each { |e| arr[e] }.some_method

Ste*_*fan 6

方法顺序是相关的:

arr.each_with_index.select { |e, i| i % 3 == 0 }
#=> [[10, 0], [40, 3], [70, 6], [100, 9]]
Run Code Online (Sandbox Code Playgroud)

与:

arr.select.each_with_index { |e, i| i % 3 == 0 }
#=> [10, 40, 70, 100]
Run Code Online (Sandbox Code Playgroud)

由于select返回枚举器,您还可以使用Enumerator#with_index:

arr.select.with_index { |e, i| i % 3 == 0 }
#=> [10, 40, 70, 100]
Run Code Online (Sandbox Code Playgroud)

关于切片等效项,您可以使用map(或其别名collect)来收集数组中的项:

(0..arr.length).step(3).map { |e| arr[e] }
#=> [10, 40, 70, 100]
Run Code Online (Sandbox Code Playgroud)

或者values_at获取给定索引处的项目:

arr.values_at(*(0..arr.length).step(3))
#=> [10, 40, 70, 100]
Run Code Online (Sandbox Code Playgroud)

*将参数转换为数组(via to_a)然后转换为参数列表,即:

arr.values_at(*(0..arr.length).step(3))
arr.values_at(*(0..arr.length).step(3).to_a)
arr.values_at(*[0, 3, 6, 9])
arr.values_at(0, 3, 6, 9)
Run Code Online (Sandbox Code Playgroud)

略短:

arr.values_at(*0.step(arr.size, 3))
#=> [10, 40, 70, 100]
Run Code Online (Sandbox Code Playgroud)


Seb*_*lma 5

您可以使用each_slice以下方法迭代arr并 获取“三个”元素each_slice(3)

\n\n
p arr.each_slice(3).to_a\n# => [[10, 20, 30], [40, 50, 60], [70, 80, 90], [100]]\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,有了该数组,您可以看到每个第一个元素都是您想要获取的输出中的一个元素,因此您可以使用map和 来获取第一个元素:

\n\n
arr = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]\np arr.each_slice(3).map(&:first)\n# => [10, 40, 70, 100]\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以将其用作.map{|e| e.first}, 或.map{|e|\xc2\xa0e[0]},但对于较短的版本,您可以仅使用.map(&:first).

\n