Appending elements to a list

I have a list. I am trying to choose specific combinations from that list and making a list of list of those combinations.
My code runs something like this:

n = 6
list = [1,2,3,4,5,6]
n_list = []
for i <- n…1 do
temp_list = List.delete_at(list,i-1)
[temp_list | n_list]
end

So basically i am removing one element at a time adding the resultant list to my list of list. temp_list is getting created correctly in each iteration. However that the end of the for n_list is still empty.

Remember that in Elixir, all variables are immutable. So what you’’e doing there simply has no effect, neither on list nor on n_list. At the end of this code, list and n_list still point to the same values as they did before.

All data in elixir is immutable, it can’t be changed or altered. Instead you need to think about having functions that return transformed data. What should the output of this process look like?

Do I understand you correctly, that you want to have a list of tails?

So for [1,2,3] you want to have [[1,2,3],[2,3],[3],[]]?

def tails(list) when is_list(list), do: tails(list, [list])

defp tails([], acc), do: Enum.reverse(acc)
defp tails([_|t], acc), do: tails(t, [t | acc])

If I did not understand you correctly, can you please get a bit more into detail and show some sample input and expected output?

i want [[2,3],[1,3],[1,2]]

So basically this?

def foo(list) when is_list(list) do
  for i <- (Enum.count(list) - 1), do: List.delete_at(list, i)
end

The culprit is, that this is O(n²), since List.delete_at/2 is O(n) and we call it n times… I’m not sure though if one can do this in something better… Intuitively O(n) can’t be achieved, but perhaps something inbetween?


Anyway… I’m not sure what this has to do with “appending to a list” as written in the title… Can you perhaps think about it and rephrase the question?

Do you want something like this?

iex(1)> list = [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
iex(2)> for x <- list, y <- list, x < y, do: [x,y]
[[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 3], [2, 4], [2, 5], [2, 6], [3, 4],
 [3, 5], [3, 6], [4, 5], [4, 6], [5, 6]]

I wanted to some like [[2, 3, 4, 5, 6], [1, 3, 4, 5, 6], [1, 2, 4, 5, 6], [1, 2, 3, 5, 6], [1, 2, 3, 4, 6], [1, 2, 3, 4, 5]]

I think the basic issue was due to variables being immutable. I got the solution using recursion instead of for. Some thing like this-

def my_function(i,n,list,n_list) do
  if i < n do
    n_list = my_function(i+1,n,list,n_list) ;
  end
  temp_list = List.delete_at(list,i-1) ;
  [ temp_list | n_list] ;
end

calling it using new_list = my_function(1,n,list,[]) ;

where list = [1,2,3,4,5,6]

Suggestions for corrections and improvements are welcomed :slight_smile:

You can get that result with my function shown in Appending elements to a list

Your function does use imperative assignement and will produce warnings in Elixir 1.4 and newer (perhaps earlier, I’m not sure exactly when this has been deprecated) and will not work anymore in 2.0.

A version that works better were this:

def foo(list) when is_list(list), do: foo(list, Enum.count(list), [])

defp foo(list, 0, acc), do: acc
defp foo(list, n, acc) when n > 0, do: foo(list, n - 1, [List.delete_at(list, n - 1) | acc])

It has the same problems according runtime as my already shown version using for.