Magic First and Last Indicator in a Loop in Ruby/Rails?

前端 未结 16 2345
眼角桃花
眼角桃花 2020-12-08 00:01

Ruby/Rails does lots of cool stuff when it comes to sugar for basic things, and I think there\'s a very common scenario that I was wondering if anyone has done a helper or s

16条回答
  •  执笔经年
    2020-12-08 00:39

    I could not resist :) This is not tuned for performance although i guess it is should not be much slower than most of the other answers here. It's all about the sugar!

    class Array
      class EachDSL
        attr_accessor :idx, :max
    
        def initialize arr
          self.max = arr.size
        end
    
        def pos
          idx + 1
        end
    
        def inside? range
          range.include? pos
        end
    
        def nth? i
          pos == i
        end
    
        def first?
          nth? 1
        end
    
        def middle?
          not first? and not last?
        end
    
        def last?
          nth? max
        end
    
        def inside range
          yield if inside? range
        end
    
        def nth i
          yield if nth? i
        end
    
        def first
          yield if first?
        end
    
        def middle
          yield if middle?
        end
    
        def last
          yield if last?
        end
      end
    
      def each2 &block
        dsl = EachDSL.new self
        each_with_index do |x,i|
          dsl.idx = i
          dsl.instance_exec x, &block
        end
      end
    end
    

    Example 1:

    [1,2,3,4,5].each2 do |x|
      puts "#{x} is first"  if first?
      puts "#{x} is third"  if nth? 3
      puts "#{x} is middle" if middle?
      puts "#{x} is last"   if last?
      puts
    end
    
    # 1 is first
    # 
    # 2 is middle
    # 
    # 3 is third
    # 3 is middle
    # 
    # 4 is middle
    # 
    # 5 is last
    

    Example 2:

    %w{some short simple words}.each2 do |x|
      first do
        puts "#{x} is first"
      end
    
      inside 2..3 do
        puts "#{x} is second or third"
      end
    
      middle do
        puts "#{x} is middle"
      end
    
      last do
        puts "#{x} is last"
      end
    end
    
    # some is first
    # short is second or third
    # short is middle
    # simple is second or third
    # simple is middle
    # words is last
    

提交回复
热议问题