我怎么能实现这个?我认为我的解决方案很脏,我想做得更好。我认为在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)
答案 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]