loop over list in elixir without creating nil values

I have an interesting situation. I'm looping over a list several times and I don't know how to produce the list I want. I'm essentially trying to order the second tuple in a list of tuples according to the order of an outside list.

aclist = [{2,4},{2,6},{4,1},{4,8},{1, 2},{1,5},{3,3},{3,7}]
plist = [1,2,3,4]
newplist = 
for pid <- plist do
  Enum.map(aclist, fn({p_id,c_id}) ->
    if p_id == pid do
      c_id
    end
  end)
end

the output from this code is:

[[2, 5, nil, nil, nil, nil, nil, nil], [nil, nil, 4, 6, nil, nil, nil, nil],
 [nil, nil, nil, nil, 3, 7, nil, nil], [nil, nil, nil, nil, nil, nil, 1, 8]]

I need the output to be [2,5,4,6,3,7,1,8] but that would require me to loop over it again in a nested loop to pull those numbers out. So obviously I'm missing something, how do I loop over it and pull out the correct data the first time?

1 answer

  • answered 2017-06-17 19:17 Dogbert

    for is the perfect thing to use here. It allows iterating over multiple lists while producing a flat list as result and also allows filtering:

    iex(1)> aclist = [{2,4},{2,6},{4,1},{4,8},{1, 2},{1,5},{3,3},{3,7}]
    [{2, 4}, {2, 6}, {4, 1}, {4, 8}, {1, 2}, {1, 5}, {3, 3}, {3, 7}]
    iex(2)> plist = [1,2,3,4]
    [1, 2, 3, 4]
    iex(3)> for pid <- plist, {p_id, c_id} <- aclist, p_id == pid, do: c_id
    [2, 5, 4, 6, 3, 7, 1, 8]