3

我怎么能实现这个?我认为我的解决方案很脏,我想做得更好。我认为在 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 方式,因为我认为这有助于提高代码的可读性,而且我是一个很好的可读代码迷 :) 我扩展了核心类“Array”,现在我可以对项目中的每个数组执行以下操作:

>> 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 Grid 系统 ( http://960.gs )

4

8 回答 8

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"]
于 2009-12-10T17:05:00.540 回答
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

于 2009-12-10T17:08:04.170 回答
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"]
于 2009-12-10T16:58:05.683 回答
3

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

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

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

于 2009-12-10T18:34:27.963 回答
2

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

(0...((fruits.size+1-offset)/mod)).map {|i| fruits[i*mod+offset]}
于 2009-12-10T18:42:59.553 回答
1

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

拉出均匀的水果(记得压紧以在最后拉出零点):

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"]
于 2009-12-10T17:44:53.330 回答
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 }
于 2009-12-10T19:35:38.887 回答
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]
于 2009-12-10T19:39:53.277 回答