【问题标题】:Elixir templates - looping through a list with iterator valueElixir 模板 - 遍历具有迭代器值的列表
【发布时间】:2016-08-09 12:02:35
【问题描述】:

来自其他编程语言,许多像我这样的人会感到惊讶。我有一个简单的问题。我有一个列表 - 比如说,用户。我想遍历用户并显示一些信息。很简单,直到我被这个难住了:

使用 eex 模板,我试图这样做:

<%= for i <- 0..length(@users) do %>
  <% user = Enum.at(@users) %>

  <!-- every third user, I need to display on a new "row" -->
  <%= if rem(i,3) == 0 do %>
    <div class="row">
  <% end %>

  <!-- display user information - like user name -->
  <%= user.name %>

  <!-- then close out the "row" tag if we are due for starting another on the next iteration -->

   <%= if rem(i+1,3) == 0 do %>
    <div class="row">
  <% end %> 

<% end %>

首先,用户价值变成了零。不知道为什么。其次,我对此没有任何解释。

“user = Enum.at(@users, i)”和 有什么区别?在后一种情况下,用户不为零。

最后,通过列表跟踪时间并采取稍微不同的操作(如上例中的新行开始用户)的最佳方法是什么?

为了简单起见,我还忽略了这样一个事实,即我们可能没有最后一个结束“/div”标记的行(这取决于列表中的用户数量)。为了专注于手头的问题,我忽略了任何逻辑。

【问题讨论】:

    标签: elixir


    【解决方案1】:

    user = Enum.at(@users, i)&lt;%= for user &lt;- @users %&gt; 有什么区别?在后一种情况下,用户不为零。

    您应该在最后一次迭代中获得user = nil。那是因为您从0 循环到length(@users),并且最后一个迭代值将是length(@users),它比列表中最后一个有效索引多1,因为索引是基于0 的。您应该从0 循环到length(@users) - 1。请注意,如果@users 为空Enum.to_list(0..-1) #=&gt; [0, -1],这将导致问题。

    最后,通过列表跟踪时间并采取稍微不同的操作(如上例中的新行开始用户)的最佳方法是什么?

    我会使用Enum.with_indexif。此外,Elixir 中的 length 是一个缓慢的 (O(n)) 操作,因此最好将其值缓存在循环之外,而不是在每次迭代时重新计算它。我也相信您打算在第二个if 中打印"&lt;/div&gt;"。这是最终代码:

    <% users_length = length(@users) %>
    <%= for {user, i} <- Enum.with_index(@users) %>
      <%= if rem(i, 3) == 0, do: ~s|<div class="row"| %>
      <%= user.name %>
      <%= if rem(i + 1, 3) == 0 || i + 1 == users_length, do: "</div>" %>
    <% end %>
    

    【讨论】:

    • &lt;%= for {user, i} &lt;- Enum.with_index(@users) do %&gt; 中缺少do
    【解决方案2】:

    我认为一个问题是您需要从0 to length - 1 循环,而不是0 to length。因为你一直循环到最后一次递归,Enum.at(@users, length) 给了nil

    【讨论】:

      【解决方案3】:

      我最终使用了 Enum.with_index(@users) 这也给了我理解范围内的索引,但我仍然想从一些专家那里了解上面看到的行为。为了他人的利益,这是我想出的解决方案(也许有更好的解决方案。很想听听)

      <%= for {user, i} <- Enum.with_index(@users) do %>
      
        <!-- every third user, I need to display on a new "row" -->
        <%= if rem(i,3) == 0 do %>
          <div class="row">
        <% end %>
      
        <!-- display user information - like user name -->
        <%= user.name %>
      
        <!-- then close out the "row" tag if we are due for starting another on the next iteration -->
      
         <%= if rem(i+1,3) == 0 || (i+1) > length(@users) do %>
          <div class="row">
        <% end %> 
      
      <% end %>
      

      【讨论】:

        猜你喜欢
        • 2020-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-03
        • 1970-01-01
        • 2010-10-21
        • 2020-09-13
        • 2019-01-25
        相关资源
        最近更新 更多