Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby-哈希数组-从哈希值中嵌套HTML菜单,无需写入重复项_Html_Ruby_Hash_Nested - Fatal编程技术网

Ruby-哈希数组-从哈希值中嵌套HTML菜单,无需写入重复项

Ruby-哈希数组-从哈希值中嵌套HTML菜单,无需写入重复项,html,ruby,hash,nested,Html,Ruby,Hash,Nested,我有一个相对较大的散列,其中所有键的值都是散列数组(见下面的示例布局)。在过去的4.5个小时里,我一直在尝试为我的Rails应用程序编写HTML,我真的快要哭了,因为我一直在兜圈子,却没有任何东西可以展示出来 非常感谢您的帮助,并提前感谢您的时间 遇到的具体问题 章节/诗句出现在它们不对齐的书籍上 我也无法消除重复条目,例如,“第4章”出现了多次(而不是一次出现,下面嵌套了多个章节/诗句引用) 所需的解决方案标准 HTML需要分3层/嵌套编写(第一层/包含书名的div(如《创世纪》、《出埃及记》

我有一个相对较大的散列,其中所有键的值都是散列数组(见下面的示例布局)。在过去的4.5个小时里,我一直在尝试为我的Rails应用程序编写HTML,我真的快要哭了,因为我一直在兜圈子,却没有任何东西可以展示出来

非常感谢您的帮助,并提前感谢您的时间

遇到的具体问题

  • 章节/诗句出现在它们不对齐的书籍上
  • 我也无法消除重复条目,例如,“第4章”出现了多次(而不是一次出现,下面嵌套了多个章节/诗句引用)
  • 所需的解决方案标准

  • HTML需要分3层/嵌套编写(第一层/包含书名的div(如《创世纪》、《出埃及记》、《利未记》),第二层/包含章节的div,第三层/包含诗句的div)

  • 章节和诗句必须对齐(例如,《出埃及记》2:7不应写入《创世纪》第2章菜单)

  • 书名应按
    hsh
    的键顺序书写(如《创世记》后面跟着《出埃及记》,后面跟着《利未记》,而不是按字母顺序)

  • 数据格式:

    hsh = { :genesis =>
                 [
                     {:id => 1, :verse => 'Genesis 4:12'},
                     {:id => 1, :verse => 'Genesis 4:23-25'},
                     {:id => 2, :verse => 'Genesis 6:17'}
                 ],
            :exodus =>
                 [
                     {:id => 5, :verse => 'Exodus 2:7'},
                     {:id => 3, :verse => 'Exodus 2:14-15'},
                     {:id => 4, :verse => 'Exodus 12:16'}
                 ],
            :leviticus =>
                 [
                     {:id => 2, :verse => 'Leviticus 11:19-21'},
                     {:id => 7, :verse => 'Leviticus 15:14-31'},
                     {:id => 7, :verse => 'Leviticus 19:11-12'}
                 ]
         }
    
    所需的输出HTML[为简洁起见缩短]

    <div class="submenu">
        <a href="#">Genesis</a>
        <div class="lvl-2">
            <div>
                <div class="submenu">
                    <a>Chapter 4</a>
                    <div class="lvl-3">
                        <div>
                            <a onclick="load('1')"><span>ID 1</span> Verse 12</a>
                            <a onclick="load('1')"><span>ID 1</span> Verse 23-25</a>
                        </div>
                    </div>
                </div>
                <div class="submenu">
                    <a>Chapter 6</a>
                    <div class="lvl-3">
                        <div> <a onclick="load('2')"><span>ID 2</span> Verse 17</a> </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="submenu">
            <a href="#">Exodus</a>
            <div class="lvl-2">
                <div>
                    <div class="submenu">
                        <a>Chapter 2</a>
                        <div class="lvl-3">
                            <div>
                                <a onclick="load('5')"><span>ID 5</span> Verse 7</a>
                                <a onclick="load('3')"><span>ID 3</span>Verse 14-15</a>
                            </div>
                        </div>
                    </div>
                    <div class="submenu">
                        <a>Chapter 12</a>
                        <div class="lvl-3">
                            <div>
                                <a onclick="load('4')"><span>ID 4</span> Verse 16</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            ## Shortened for brevity (Leviticus references excluded)
        </div>
    </div>
    
    
    第二章
    ID 5第7节
    ID 3第14-15节
    第十二章
    ID 4第16节
    ##为简洁而缩短(利未记参考文献除外)
    
    代码

    final_html = String.new
    
    hsh.each do |book, verse_array|
    
        verse_array.each do |reference|
    
          book = reference[:verse].split(' ').first           # => "Genesis"
          full_verse = reference[:verse].split(' ').last      # => "4:12"
          chapter = full_verse.split(':').first               # => "4"
          verse = full_verse.split(':').first                 # => "12"
    
          # Failing Miserably at appending the right HTML to the final_html string here...
          # final_html << "<div class=\"submenu\">"
          # final_html << ...
          # final_html << ...
    
        end
    end
    
    final\u html=String.new
    每一本书,每一首诗|
    韵文|数组。每个do |引用|
    书=参考文献[:韵文]。拆分(“”)。第一个#=>“创世记”
    全文=参考[:韵文]。拆分(“”)。最后一个#=>“4:12”
    章=完整的诗。分开(“:”)。第一个“=>”4“
    韵文=完整韵文。拆分(“:”)。第一个#=>“12”
    #在这里将正确的HTML附加到最后的HTML字符串时失败得很惨。。。
    
    #final_html与此类问题的常见情况一样,一旦将数据放入与所需输出非常相似的“形状”中,解决问题就会变得容易得多。您的输出是嵌套的树结构,因此您的数据也应该是嵌套的。让我们先做吧。以下是您的数据:

    data = {
      genesis: [
        { id: 1, verse: "Genesis 4:12" },
        { id: 1, verse: "Genesis 4:23-25" },
        { id: 2, verse: "Genesis 6:17" }
      ],
      exodus: [
        { id: 5, verse: "Exodus 2:7" },
        # ...
      ],
      # ...
    }
    
    现在暂且不考虑HTML,下面是我们想要的结构:

    Genesis
    第四章
    ID 1-第12节
    ID 1-第23-25节
    第六章
    ID 2-第17节
    离去
    第二章
    ID 5-第7节
    ...
    ...
    
    关于您的数据,我注意到的第一件事是,它具有您不需要的嵌套级别。由于
    :verse
    值包含书名,因此我们不需要外部散列中的键(
    :genesis
    等),只需将所有内部散列展平为一个数组:

    data.values.flatten
    # => [ { id: 1, verse: "Genesis 4:12" },
    #      { id: 1, verse: "Genesis 4:23-25" },
    #      { id: 2, verse: "Genesis 6:17" }
    #      { id: 5, verse: "Exodus 2:7" },
    #      # ... ]
    
    现在我们需要一种方法来从
    :verse
    字符串中提取书籍、章节和韵文。如果需要,可以使用
    String#split
    ,但Regexp也是一个不错的选择:

    VERSE_EXPR = /(.+)\s+(\d+):(.+)$/
    
    def parse_verse(str)
      m = str.match(VERSE_EXPR)
      raise "Invalid verse string!" if m.nil?
      book, chapter, verse = m.captures
      { book: book, chapter: chapter, verse: verse }
    end
    
    flat_data = data.values.flatten.map do |id:, verse:|
      { id: id }.merge(parse_verse(verse))
    end
    # => [ { id: 1, book: "Genesis", chapter: "4", verse: "12" },
    #      { id: 1, book: "Genesis", chapter: "4", verse: "23-25" },
    #      { id: 2, book: "Genesis", chapter: "6", verse: "17" },
    #      { id: 5, book: "Exodus", chapter: "2", verse: "7" },
    #      # ... ]
    
    现在可以很容易地按书本对数据进行分组:

    books = flat_data.group_by {|book:, **| book }
    # => { "Genesis" => [
    #        { id: 1, book: "Genesis", chapter: "4", verse: "12" },
    #        { id: 1, book: "Genesis", chapter: "4", verse: "23-25" },
    #        { id: 2, book: "Genesis", chapter: "6", verse: "17" }
    #      ],
    #      "Exodus" => [
    #        { id: 5, book: "Exodus", chapter: "2", verse: "7" },
    #        # ...
    #      ],
    #      # ...
    #    }
    
    …在每本书中,按章节:

    books_chapters = books.map do |book, verses|
      [ book, verses.group_by {|chapter:, **| chapter } ]
    end
    # => [ [ "Genesis",
    #        { "4" => [ { id: 1, book: "Genesis", chapter: "4", verse: "12" },
    #                   { id: 1, book: "Genesis", chapter: "4", verse: "23-25" } ],
    #          "6" => [ { id: 2, book: "Genesis", chapter: "6", verse: "17" } ]
    #        }
    #      ],
    #      [ "Exodus",
    #        { "2" => [ { id: 5, book: "Exodus", chapter: "2", verse: "7" },
    #                   # ... ],
    #          # ...
    #        }
    #      ],
    #      # ...
    #    ]
    
    您会注意到,因为我们在
    books
    上调用了
    map
    ,所以我们的最终结果是一个数组,而不是散列。您可以调用
    使其再次成为散列,但出于我们的目的,这是不必要的(迭代键值对数组的工作原理与迭代散列的工作原理相同)

    它看起来有点凌乱,但你可以看到结构在那里:诗句嵌套在书籍的章节中。现在我们只需要把它转换成HTML

    顺便说一句,为了我们的残疾朋友:正确的 用于嵌套树结构的HTML元素是
    。如果 您需要使用
    s,但是 否则,请为使用 无障碍设备将感谢您。(已经写了许多文章 关于设计这样的树的样式,所以我不会深入讨论,但首先你可以 使用
    列表样式类型隐藏项目符号:无;

    我没有可以使用的Rails应用程序,所以为了生成HTML,我只使用Ruby标准库中的ERB。除了如何将变量传递给视图之外,它在Rails中看起来或多或少是相同的

    require "erb"
    
    VIEW = <<END
    <ul>
    <% books.each do |book_name, chapters| %>
      <li>
        <a href="#"><%= book_name %></a>
        <ul>
        <% chapters.each do |chapter, verses| %>
          <li>
            <a href="#">Chapter <%= chapter %></a>
            <ul>
            <% verses.each do |id:, verse:, **| %>
              <li>
                <a onclick="load(<%= id %>)">ID <%= id %>: Verse <%= verse %></a>
              </li>
            <% end %>
            </ul>
          </li>
        <% end %>
        </ul>
      </li>
    <% end %>
    </ul>
    END
    
    def render(books)
       b = binding
       ERB.new(VIEW, nil, "<>-").result(b)
    end
    
    puts render(books_chapters)
    
    需要“erb”
    
    VIEW=All,我意识到我提供的代码没有显示出太多的努力,但我向你保证,我花了数小时尝试各种迭代策略,等等。现在在Rubymine中,我有大约210行垃圾,大部分都被注释掉了,试图解释我尝试过的所有技术会让这个问题变得太长。它已经可以说是在更长的一边。再次感谢你的帮助。你有什么错误吗?嗨,迪内什,不是很明确。我以多种不同的方式迭代了散列数组,生成的HTML没有任何错误——它的顺序和重复性非常糟糕。谢谢你伸出援手。非常感谢。你能帮忙吗?我比你想象的更爱你。。。非常感谢你写了这篇详细的、冗长的、可能会让人筋疲力尽的文章。非常感谢你的时间。我今晚或很快就会试试这个!乔丹,我想我还没有获得PM的许可,否则我会直接问。你可以接受捐款来帮助别人吗?如果是这样,请提供您的贝宝或类似!谢谢你,乔丹。这很有效。请注意,在早期版本中