Enum intersperse

elixir, intersperse, sorting, phoenix – Nov 24 2018

Intersperse is the action of putting something in between other things.

• • •

In your Elixir application you might find yourself needing to output a string of comma separated names. You could do something like this as your first attempt but, this approach creates an extra comma and white space.


# Step 1
users = ["tony", "sam", "alex"]

# Step 2 - Add a comma to each name
list = for user <- users  do
   "#{user}" <> ", "
end

# Step 3 - Joinh into a string
Enum.join(list, "")

# "tony,  sam,  alex, "

What you want is the comma to appear in between the names. This is whereEnum.interprese/2 can help out.


# Step 1
users = ["tony", "sam", "alex"]
# ["tony", "sam", "alex"]

# Step 2 - Look at the commas within the list
list = Enum.intersperse(users, ", ")
# ["tony", ", ", "sam", ", ", "alex"]

# Step 3 - Join into a string
Enum.join(list, "")

# "tony, sam, alex"

This approach is much better. By using Enum.interprese/2 and Enum.join/2 you can achieve the result you were looking for.

However, our application is interactive and we need to get these names clickable. Let’s see how we can do this in a Phoenix application.

Real World Example

In my Phoenix application I have a list of users that need to be separated by a comma. Each user needs to be clickable but the comma needs to be plain text. In order to do this we are going to create a helper.

Create a shared_view.ex file within the views directory. This module is going to contain common functions that will be used across the application.


defmodule DemoWeb.SharedView do
  use DemoWeb, :view

  def linked_users(conn, users) do
    users
      |> Enum.map(fn(users) ->
        link(users.name, to: user_path(conn, :show, user.name), title: "See #{user.name} content")
      end)
      |> Enum.intersperse(", ")
  end

end

With DemoWeb.SharedView.linked_users/2 you pass in the current conn and the users. The function will then map through each user in the users list and apply the link/2 function to each user.

Once the map function has gone through the list, it returns a List containing HTML links. This list will then be passed into the Enum.interprese/2 as the first argument thanks to the |> and we pass in the ", " as the second argument. The result is we get an HTML presentation of links being separated by a comma.

Using the shared view

In my templates/shared directory I will use this as a template to render the list of users

&lt;p&gt;
&lt;%= linked_users(@conn, @users) %&gt;
&lt;/p&gt;

In my Phoenix web app, I have a home page that shows some @users. So, I can now render the DemoWeb.SharedView module by calling that users.html and passing in the arguments as shown below

&lt;section&gt;
  &lt;div class=&quot;container user-listing&quot;&gt;
   &lt;%= render DemoWeb.SharedView, &quot;users.html&quot;, conn: @conn, users: @users,  %&gt;
  &lt;/div&gt;
&lt;/section&gt;

Then my application should output HTML that looks something like this

&lt;section&gt;
  &lt;div class=&quot;container user-listing&quot;&gt;
   &lt;p&gt;
   &lt;a href=&quot;/user/tony&quot; title=&quot;See tony content&quot;&gt;tony&lt;/a&gt;,
   &lt;a href=&quot;/user/sam&quot; title=&quot;See sam content&quot;&gt;sam&lt;/a&gt;,
   &lt;a href=&quot;/user/alex&quot; title=&quot;See alex content&quot;&gt;alex&lt;/a&gt;
   &lt;/p&gt;
  &lt;/div&gt;
&lt;/section&gt;
Follow on Twitter
Follow on Github