25

我正在尝试创建一个脚本来遍历索引,查看每个页码,然后告诉我该条目所在的书的哪一章。这是我正在做的事情的近似值:

@chapters = {
  1 => "introduction.xhtml",
  2..5 => "chapter1.xhtml",
  6..10 => "chapter2.xhtml",
  11..18 => "chapter3.xhtml",
  19..30 => "chapter4.xhtml" }

def find_chapter(number)
  @chapters.each do |page_range, chapter_name|
    if number === page_range
      puts "<a href=\"" + chapter_name + "\page" + number.to_s + "\">" + number.to_s + </a>"
    end
  end
end

find_chapter(1)会吐出我想要的字符串,但find_chapter(15)不返回任何内容。不能像这样使用范围作为键吗?

4

6 回答 6

37

您可以使用哈希键的范围,并且可以使用以下方法非常轻松地查找键select

@chapters = { 1 => "introduction.xhtml", 2..5 => "chapter1.xhtml", 
              6..10 => "chapter2.xhtml", 11..18 => "chapter3.xhtml",                                         
              19..30 => "chapter4.xhtml" } 

@chapters.select {|chapter| chapter === 5 }
 #=> {2..5=>"chapter1.xhtml"} 

如果您只想要章节名称,只需添加.values.first如下:

@chapters.select {|chapter| chapter === 9 }.values.first
 #=> "chapter2.xhtml" 
于 2014-05-05T14:14:32.377 回答
9

这是只返回第一个匹配键的值的简洁方法:

# setup
i = 17; 
hash = { 1..10 => :a, 11..20 => :b, 21..30 => :c }; 

# find key
hash.find { |k, v| break v if k.cover? i }
于 2014-08-02T07:40:29.697 回答
7

当然,只是颠倒比较

if page_range === number

像这样

@chapters = {
  1 => "introduction.xhtml",
  2..5 => "chapter1.xhtml",
  6..10 => "chapter2.xhtml",
  11..18 => "chapter3.xhtml",
  19..30 => "chapter4.xhtml" }

def find_chapter(number)
  @chapters.each do |page_range, chapter_name|
    if page_range === number
      puts chapter_name
    end
  end
end

find_chapter(1)
find_chapter(15)
# >> introduction.xhtml
# >> chapter3.xhtml

它以这种方式工作,因为===Range 上的方法具有特殊行为:Range#===。如果您number先放置,则Fixnum#===调用 then ,它以数字方式比较值。范围不是数字,因此它们不匹配。

于 2013-07-08T19:18:27.813 回答
7

正如@Sergio Tulentsev 演示的那样,这是可以做到的。然而,通常的方法是使用case when. 它更灵活一点,因为您可以在then子句中执行代码,并且可以使用else处理未处理的所有内容的部分。===它在引擎盖下使用相同的方法。

def find_chapter(number)
  title = case number
    when 1      then "introduction.xhtml"
    when 2..5   then "chapter1.xhtml"
    when 6..10  then "chapter2.xhtml"
    when 11..18 then "chapter3.xhtml"
    when 19..30 then "chapter4.xhtml"
    else "chapter unknown"
  end
  #optionally: do something with title
end
于 2013-07-08T19:40:23.907 回答
4

找到一个关于这个主题的论坛。他们建议

class RangedHash
  def initialize(hash)
    @ranges = hash
  end

  def [](key)
    @ranges.each do |range, value|
      return value if range.include?(key)
    end
    nil
  end
end

现在你可以像这样使用它了

ranges = RangedHash.new(
  1..10 => 'low',
  21..30 => 'medium',
  41..50 => 'high'
)
ranges[5]  #=> "low"
ranges[15] #=> nil
ranges[25] #=> "medium"
于 2016-10-30T03:25:33.543 回答
2

试试这个:

def find_chapter(page_number)
  @chapters.select{ |chapters_key| chapters_key === page_number.to_i}.values.first
end

然后你简单地这样称呼它:

find_chapter(10)
=> "chapter2.xhtml"


find_chapter(40)
=> nil
于 2018-05-25T10:17:57.403 回答