Ruby / Rails:从数组中获取索引可被x整除的元素

时间:2009-12-10 16:45:55

标签: ruby-on-rails ruby arrays modulo

我怎么能实现这个?我认为我的解决方案很脏,我想做得更好。我认为在Ruby中有一种简单的方法可以做到这一点,但我不记得了。我想在Rails中使用它,所以如果Rails提供类似的东西也可以。用法应该是这样的:

fruits = ['banana', 'strawberry', 'kiwi', 'orange', 'grapefruit', 'lemon', 'melon']

# odd_fruits should contain all elements with odd indices (index % 2 == 0)
odd_fruits = array_mod(fruits, :mod => 2, :offset => 0)

# even_fruits should contain all elements with even indices (index % 2 == 1)
even_fruits = array_mod(fruits, :mod => 2, :offset => 1)

puts odd_fruits
  banana
  kiwi
  grapefruit
  melon

puts even_fruits
  strawberry
  orange
  lemon

*******编辑*******

对于那些想知道的人,这就是我最终做的事情:

在rails项目中,我创建了一个新文件config/initializers/columnize.rb,如下所示:

class Array
  def columnize args = { :columns => 1, :offset => 0 }
    column = []
    self.each_index do |i|
      column << self[i] if i % args[:columns] == args[:offset]
    end
    column
  end
end

Rails在加载Rails后立即自动加载这些文件。我还使用了为方法提供参数的railsy方法,因为我认为这是为了更好的可读代码的目的,我是一个很好的可读代码 - 恋物癖:)我扩展了核心类“数组”,现在我可以对项目中的每个数组执行以下操作:

>> arr = [1,2,3,4,5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]

>> arr.columnize :columns => 2, :offset => 0
=> [1, 3, 5, 7]
>> arr.columnize :columns => 2, :offset => 1
=> [2, 4, 6, 8]

>> arr.columnize :columns => 3, :offset => 0
=> [1, 4, 7]
>> arr.columnize :columns => 3, :offset => 1
=> [2, 5, 8]
>> arr.columnize :columns => 3, :offset => 2
=> [3, 6]

我现在将使用它在我的视图中的不同列中显示数据库中的条目。我喜欢它的是,我不必调用任何紧凑的方法或东西,因为当你将一个nil对象传递给视图时rails会抱怨。现在它只是有效。我也想过让JS为我做这一切,但我更喜欢这种方式,使用960网格系统(http://960.gs

8 个答案:

答案 0 :(得分:5)

fruits = ["a","b","c","d"]
even = []
x = 2 
fruits.each_index{|index|
    even << fruits[index] if index % x == 0
}
odds = fruits - even
p fruits
p even
p odds



["a", "b", "c", "d"]
["a", "c"]
["b", "d"]

答案 1 :(得分:3)

def array_mod(arr, mod, offset = 0)
  arr.shift(offset)
  out_arr = []

  arr.each_with_index do |val, idx|
    out_arr << val if idx % mod == 0
  end

  out_arr
end

用法:

>> fruits = ['banana', 'strawberry', 'kiwi', 'orange', 'grapefruit', 'lemon', 'melon']

>> odd_fruits = array_mod(fruits, 2)
=> ["banana", "kiwi", "grapefruit", "melon"]

>> even_fruits = array_mod(fruits, 2, 1)
=> ["strawberry", "orange", "lemon"]

>> even_odder_fruits = array_mod(fruits, 3, 2)
=> ["kiwi", "lemon"]

答案 2 :(得分:3)

你想要的是:

even_fruits  = fruits.select_with_index { |v,i| i % 2 == 0) }
odd_fruits = fruits - even_fruits

不幸的是Enumerable#select_with_index标准不存在,但是有些人使用这种方法扩展了Enumerable

http://snippets.dzone.com/posts/show/3746 http://webget.com/gems/webget_ruby_ramp/doc/Enumerable.html#M000058

答案 3 :(得分:3)

我能想到的最简单的方法是:

fruits = ["a","b","c","d"]
evens = fruits.select {|x| fruits.index(x) % 2 == 0}
odds = fruits - evens

如果数组可以为您查找索引,则无需弄乱select_with_index。我想这个方法的缺点是如果'fruits'中有多个具有相同值的条目(index方法只返回第一个匹配条目的索引)。

答案 4 :(得分:2)

仅使用核心功能的解决方案:

(0...((fruits.size+1-offset)/mod)).map {|i| fruits[i*mod+offset]}

答案 5 :(得分:1)

Rails为Array提供ActiveSupport扩展,提供“in_groups_of”方法。这就是我通常用于这样的事情。它允许你这样做:

拉出均匀的果实(记得紧凑以拉开末端的nils):

fruits = ['banana', 'strawberry', 'kiwi', 'orange', 'grapefruit', 'lemon', 'melon']
fruits.in_groups_of(2).collect{|g| g[1]}.compact
=> ["strawberry", "orange", "lemon"]

拉出奇怪的果实:

fruits.in_groups_of(2).collect{|g| g[0]}.compact
=> ["banana", "kiwi", "grapefruit", "melon"]

获得每三个水果,你可以使用:

fruits.in_groups_of(3).collect{|g| g[0]}.compact
=> ["banana", "orange", "melon"]

答案 6 :(得分:0)

功能方式

#fruits = [...]
even = []
odd = []

fruits.inject(true ){|_is_even, _el| even << _el if _is_even; !_is_even}
fruits.inject(false){|_is_odd,  _el| odd  << _el if _is_odd;  !_is_odd }

答案 7 :(得分:0)

这是一个使用#enum_for的解决方案,它允许您指定一个方法来“使用”#each:

require 'enumerator'
mod = 2
[1, 2, 3, 4].enum_for(:each_with_index).select do |item, index| 
  index % mod == 0 
end.map { |item, index| item }
# => [1, 2]