How-To Exclude results from List Comprehensions

Say we have a simple list comprehensions:

for x <- [some_list] do
  case _compute(x) do
    nil -> nil # directly exclude this value from output
    val -> val # add this value to output as usual
  end
end

Short of running the whole comprehensions, the filtering out nil values,

is there a better was to do this?

You can have a filter in your comprehension:

for n <- 1..4, rem(n, 2) == 0, do: n

EDIT:

I think I misread the question. I’d probably just use Enum.reduce instead :slight_smile:

  1. In the example you wrote the list comprehension would return the nil and other values i.e. the case does not filter out nil
  2. Given the nil values are a result of _compute unless you know the exact values of x which would result in a _computer(x) == nil you can not prefilter the input.
  3. It is very common to generate a list of results and post-filter the results

I feel the post filter is a wasted step, if we can have a way to exclude the nil values directly, that’s my point…

still wont help… you mean Enum.filter

don’t know if you consider this better, but here’s a solution

List.foldr([1, 2, nil, 4], [], fn x, acc -> if is_nil(x), do: acc, else: [x*2|acc] end)

iex(1)> List.foldr([1, 2, nil, 4], [], fn x, acc -> if is_nil(x), do: acc, else: [x*2|acc] end)
[2, 4, 8]
iex(2)> 

edit: it’s also not clear to me whether it had to be a comprehension or not, so maybe this isn’t a solution?

Got this elegant solution from StackOverflow:

for x <- list, y = _compute(x), do: y

I think the idea is if _compute(x) is truthy, return y, else if false / nil, it will be skipped, and you only have to evaluate _compute(x) once

4 Likes

No, I mean Enum.reduce though it will look similar to your solution.

Enum.reduce(some_list, fn(x, acc)->
  case do_stuff(x) do
    nil -> acc
    other -> [other | acc]
  end
end)

That’s a nice solution :+1:

1 Like