【问题标题】:Ruby find next in arrayRuby 在数组中找到下一个
【发布时间】:2011-01-04 17:25:37
【问题描述】:

有没有办法在 Ruby 数组中找到下一项?

代码:

# Find ALL languages
if !debug
  lang = Language.all
else
  lang = Language.where("id = ? OR id = ?", 22, 32)
end

# Get all elements
elements = Element.where("human_readable IS NOT NULL")

lang.each do |l|
  code = l.code.downcase
  if File.exists?(file_path + code + ".yml")
    File.delete(file_path + code + ".yml")
  end

  t1 = Time.now

  info = {}
  elements.each do |el|
    unless l.id == 1
      et = el.element_translations.where("language_id = ? AND complete = ?", l.id, true)
    else
      et = el.element_translations.where("language_id = ?", 1)
    end
    et.each do |tran|
      info[code] ||= {}
      info[code][el.human_readable] = tran.content.gsub("\n", "").force_encoding("UTF-8").encode!
    end
  end
  File.open(file_path + code + ".yml", "w", :encoding => "UTF-8") do |f|
    if f.write(info.to_yaml)
      t2 = Time.now

      puts code + ".yml File written"
      puts "It took " + time_diff_milli(t1, t2).to_s + " seconds to complete"
      # This is where I want to display the next item in the lang array
      puts lang.shift(1).inspect
      puts "*"*50
    end
  end
end

【问题讨论】:

  • 当心puts lang.shift(1).inspect,在 lang 上迭代的块内使用它可能会导致一些问题。再说一次,它可能不会。
  • -1 表示难以理解的问题。不要只是将代码转储给我们并期望我们修复它。努力写出你的问题。
  • @Theo,我不只是向任何人“转储”代码......我只是在问一个问题......上面的代码是为了展示我所做的工作,以防万一有人需要参考它。
  • 我认为问题在于这个问题看起来很简单,很难接受你实际上在问我们认为你在问什么,即给定索引 i 处的项目 x,你如何阅读 i 处的项目 y +1。如果是这样,那么x = array[i]y = array[i+1]。这甚至不是编程 101,它是编程幼儿园,所以我们无法想象这是你要问的。这不是要冒犯,而是要澄清。
  • 在你的代码中也总是使用描述性的变量名。使用单个字母是没有意义的,实际上是糟糕的编码习惯。多花 500 毫秒来输入一个完整的单词,三个月后当你回去修复代码中的错误时,你会感谢自己。

标签: ruby arrays


【解决方案1】:

Array包含Enumerable,所以你可以使用each_with_index

elements.each_with_index {|element, index|
   next_element = elements[index+1]
   do_something unless next_element.nil?
   ...

}

【讨论】:

  • +1 需要做一些调整才能得到 OP 想要的东西,但是对正确方法的一个很好的一般描述
  • 我想你的意思是把do_something unless next_element.nil?
【解决方案2】:

如果您需要同时访问一个元素并且下一个元素是使用each_cons,那么一种迭代Enumerable 的好方法:

arr = [1, 2, 3]
arr.each_cons(2) do |element, next_element|
   p "#{element} is followed by #{next_element}"
   #...
end

# => "1 is followed by 2", "2 is followed by 3".

正如 Phrogz 所指出的,Enumerable#each_cons 在 Ruby 1.8.7+ 中可用;对于 Ruby 1.8.6,您可以require 'backports/1.8.7/enumerable/each_cons'

正如@Jacob 指出的那样,另一种方法是使用each_with_index

【讨论】:

  • 郑重声明,each_cons 仅适用于 1.8.7+(不适用于 1.8.6)。
  • @Phrogz:确实!我是通常指出这一点的人。答案已更新
【解决方案3】:
arr[n..-1].find_index(obj) + n

【讨论】:

    【解决方案4】:

    基于 Marc-Andrés 不错的答案,我想提供一个答案,以一种通用的方式,通过填充 nil所有 元素(也是最后一个元素)提供以下元素:

    arr = [1, 2, 3]
    [arr, nil].flatten.each_cons(2) do |element, next_element|
       p "#{element} is followed by #{next_element || 'nil'}"
    end
    
    # "1 is followed by 2"
    # "2 is followed by 3"
    # "3 is followed by nil"
    

    现在,当我们这样做的时候,我们还可以为所有元素提供前面的元素:

    arr = [1, 2, 3]
    [nil, arr, nil].flatten.each_cons(3) do |prev_element, element, next_element|
      p "#{element} is preceded by #{prev_element || 'nil'} and followed by #{next_element || 'nil'}"
    end
    
    # "1 is preceded by nil and followed by 2"
    # "2 is preceded by 1 and followed by 3"
    # "3 is preceded by 2 and followed by nil"
    

    【讨论】:

      【解决方案5】:

      或将其添加到您的项目中,然后您可以在任何您喜欢的数组上调用next_item(item) 方法。

      class Array
        def next_item(item)
           self[self.find_index(item) + 1] unless self.find_index(item).nil?
        end
      end
      

      注意在我提出的答案中使用self。我认识到使用self 在某种意义上是多余和不必要的。我更喜欢使用self 比需要更频繁地使代码更明显,尤其是对于初级程序员。简单,即使需要更多字符,对我来说也很重要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-20
        • 2012-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多