I want a list which consists of the indexes of the integers present in a list.

For ex: for a given list [1,2,3,4,5,‘a’]
i want output as [0,1,2,3,4] but i am getting output
[0]
[1]
[2]
[3]
[4]

the following is the code which i tried
items = [1,2,3,4,5,“a”]
list = []
items
|> Enum.with_index
|> Enum.each(fn({x,i}) →
if is_integer(x)==true do
IO.inspect list ++ [i]

end
end)

The reason you are getting outputs in separate lines, is because you are using IO.inspect on each element. Instead you should use a single inspect after accumulating your result in one array!

Try a more Elixir way!

  • Instead of using if to check if an element is number, use a filter to filter out bad stuff.
  • Instead of doing two things in one function, use separate functions.
  • Prefer pipelining.
  • Do operations after filtering is done, so you have reduced amount of elements to loop through.
  • Use LiveBook, for faster debugging of pipeline.

etc.


items = [1, 2, 3, 4, 5, "a"]

items #=> [1, 2, 3, 4, 5, "a"]
|> Enum.filter(fn x -> is_integer(x) end) #=> [1, 2, 3, 4, 5]
|> Enum.with_index() #=> [{1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}]
|> Enum.map(fn {_, i} -> i end) #=> [0, 1, 2, 3, 4]
|> dbg()

Maybe even use stream for bigger list!! (Just replace Enum with Stream) :wink:

items = [1, 2, 3, 4, 5, "a"]

items #=> [1, 2, 3, 4, 5, "a"]
|> Stream.filter(fn x -> is_integer(x) end) #=> [1, 2, 3, 4, 5]
|> Stream.with_index() #=> [{1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}]
|> Stream.map(fn {_, i} -> i end) #=> [0, 1, 2, 3, 4]
|> Enum.to_list()
|> dbg()

If you want original index position, before characters are removed! (As @odix67 pointed out)

items = [1, 'a', 2, 'b', 4, 'c', 35, 'd', 12]

items
|> Enum.with_index()
|> Enum.filter(fn {x, _} -> is_integer(x) end)
|> Enum.map(fn {_, i} -> i end)
|> dbg() # [0, 2, 4, 6, 8]

P.S. Use backtick ```elixir to declare Elixir code while pasting in Forum or GitHub.

1 Like

I think you have to index first, as after the filter the real index is lost

    items = [1,2,3,4,5,'a']
    list =
      items
      |> Enum.with_index()
      |> Enum.filter(fn {x, _i} -> is_integer(x) end)
      |> Enum.map(fn {_, i} -> i end)
      |> Enum.to_list()
    IO.inspect(list)

1 Like

Oh, I am not sure of the requirements. I just gave the best possible answer.

If the requirement changes to give original index as output, the answer is just to re arrange the pipeline.

yes, of course, the provided test data give some room for interpretation :wink:
btw, cool, I think I must give dbg() a try …

There are many possibilities how to do this, another one with ranges:

0..(Enum.count(list) - 1) 
|> Enum.to_list()

this solution doesn’t take the filtering into account, but one of the ways to produce a list with a sequence

btw, @milindnair , welcome to the forum

Oh, I see, this should work then

list = Enum.filter(list, &is_integer/1)
0..(Enum.count(list) - 1) |> Enum.to_list()

… and what if the input data is:

[1,2,'a',4,35,'b',12]

?

So it wants the list of indexes of items with integers? Ok… I guess I misread this. Sorry, I’ve just woken up! :wink:

accepted ;-), me too

The OPs first problem is not understanding immutability, as evidenced by the use of Enum.each

For fun, assuming the original index in the list is what is desired, here’s a one-line solution using the filter capability of for comprehensions

iex(105)> items = [1,2,3,4,5,"a"]
[1, 2, 3, 4, 5, "a"]
iex(106)> for {v, n} <- Enum.with_index(items), is_integer(v), do: n
[0, 1, 2, 3, 4]
2 Likes