代码之家  ›  专栏  ›  技术社区  ›  Patrick Oscity

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

  •  3
  • Patrick Oscity  · 技术社区  · 16 年前

    我如何实现这个?我认为我的解决方案非常肮脏,我想做得更好。我觉得用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之后立即自动加载这些文件。我还使用了向一个方法提供参数的刻薄方式,因为我认为这有助于更好地阅读代码,而且我是一个很好的阅读代码爱好者:)我扩展了核心类“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网格系统。( http://960.gs )

    8 回复  |  直到 15 年前
        1
  •  5
  •   OscarRyz    16 年前
    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"]
    
        2
  •  3
  •   Jordan Running    16 年前
    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"]
    
        3
  •  3
  •   bta    16 年前

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

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

    你不必乱弄 select_with_index 如果数组可以为您查找索引。我想这种方法的缺点是,如果在“水果”中有多个条目具有相同的值(即 index 方法只返回第一个匹配项的索引)。

        4
  •  3
  •   Steve Graham    15 年前

    你想要的是:

    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

        5
  •  2
  •   glenn mcdonald    15 年前

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

    (0...((fruits.size+1-offset)/mod)).map {|i| fruits[i*mod+offset]}
    
        6
  •  1
  •   Jeff Whitmire    16 年前

    Rails提供了对数组的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"]
    
        7
  •  0
  •   andrykonchin    16 年前

    功能性方式

    #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 }
    
        8
  •  0
  •   Drew Olson    16 年前

    这里有一个使用枚举for的解决方案,它允许您指定一个方法来“就地”使用每个:

    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]
    
    推荐文章