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

发布于 2024-08-14 17:20:18 字数 1781 浏览 6 评论 0原文

我怎样才能实现这个?我认为我的解决方案很脏,我想做得更好。我认为在 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 加载后立即自动加载这些文件。我还使用了 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)

How could I implement this? I think my solution is very dirty, and I would like to do it better. I think there is an easy way to do this in Ruby, but I can't remember. I want to use it with Rails, so if Rails provides something similar that's ok, too. usage should be like this:

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

******* EDIT *******

for those wo want to know, that is what i finally did:

in a rails project, i created a new file config/initializers/columnize.rb which looks like this:

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 automatically loads these files immediately after Rails has been loaded. I also used the railsy way of supplying arguments to a method, because i think that serves the purpose of better readable code, and i'm a good-readable-code-fetishist :) I extended the core class "Array", and now i can do things like the following with every array in my project:

>> 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]

I will now use it to display entries from the database in different columns in my views. What i like about it, is that i don't have to call any compact methods or stuff, because rails complains when you pass a nil object to a view. now it just works. I also thought about letting JS do all that for me, but i like it better this way, working with the 960 Grid system (http://960.gs)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

白况 2024-08-21 17:20:18
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"]
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"]
_蜘蛛 2024-08-21 17:20:18
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"]
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

Usage:

>> 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"]
诠释孤独 2024-08-21 17:20:18

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

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

如果数组可以为您查找索引,您就不需要搞乱 select_with_index 。我认为此方法的缺点是,如果“fruits”中有多个具有相同值的条目(index 方法仅返回第一个匹配条目的索引)。

The simplest method I can think of is this:

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

You don't need to mess with select_with_index if the array can look up indices for you. I suppose the drawback to this method is if you have multiple entries in 'fruits' with the same value (the index method returns the index of the first matching entry only).

蓝戈者 2024-08-21 17:20:18

您想要的是:

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

What you want is:

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

Unfortunately Enumerable#select_with_index does not exist as standard, but several people have extended Enumerable with such a method.

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

岁月静好 2024-08-21 17:20:18

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

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

Solution using just core capabilities:

(0...((fruits.size+1-offset)/mod)).map {|i| fruits[i*mod+offset]}
油饼 2024-08-21 17:20:18

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"]

Rails provides an ActiveSupport extension to Array that provides an "in_groups_of" method. That's what I usually use for things like this. It allows you to do this:

to pull the even fruits (remember to compact to pull off nils at the end):

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

to pull the odd fruits:

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

to get every third fruit, you could use:

fruits.in_groups_of(3).collect{|g| g[0]}.compact
=> ["banana", "orange", "melon"]
老娘不死你永远是小三 2024-08-21 17:20:18

功能方式

#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 }

functional way

#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 }
故人的歌 2024-08-21 17:20:18

这是使用 #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]

Here's a solution using #enum_for, which allows you to specify a method to use "in place" of #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]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文