Elixir模板 - 使用迭代器值循环遍历列表

时间:2016-08-09 02:45:48

标签: elixir

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

使用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 %>

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

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

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

为了简单起见,我也忽略了这样一个事实,即我们可能没有最终结束&#34; / div&#34;行的标记(取决于列表中的用户数)。我忽略了解决这个问题只是为了关注手头的问题。

3 个答案:

答案 0 :(得分:5)

  

user = Enum.at(@users, i)<%= for user <- @users %>之间有什么区别?在后一种情况下,用户不是零。

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

  

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

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

<% 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 %>

答案 1 :(得分:0)

我最终使用了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 %>

答案 2 :(得分:0)

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