arraysfunctional-programmingelixir

Find indexes from list in Elixir


With Enum.find_index/2, we can find the index of an element. However, if a same element occurs several times, how can we do?

I would like to have this behavior:

iex> find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "a" end)
[0]

iex> find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "c" end)
[2]

iex> find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "b" end)
[1, 3, 4]

Thanks for any ideas.


Solution

  • I couldn't find a exact function in library, so tried to implement it. Hope it can help some.

    defmodule Sample1 do
      # combining Enum functions
      def find_indexes(collection, function) do
        Enum.filter_map(Enum.with_index(collection), fn({x, _y}) -> function.(x) end, elem(&1, 1))
      end
    end
    
    defmodule Sample2 do
      # implementing as similar way as Enum.find_index
      def find_indexes(collection, function) do
        do_find_indexes(collection, function, 0, [])
      end
    
      def do_find_indexes([], _function, _counter, acc) do
        Enum.reverse(acc)
      end
    
      def do_find_indexes([h|t], function, counter, acc) do
        if function.(h) do
          do_find_indexes(t, function, counter + 1, [counter|acc])
        else
          do_find_indexes(t, function, counter + 1, acc)
        end
      end
    end
    
    IO.puts "Sample1"
    IO.inspect Sample1.find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "a" end)
    IO.inspect Sample1.find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "c" end)
    IO.inspect Sample1.find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "b" end)
    
    IO.puts "Sample2"
    IO.inspect Sample2.find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "a" end)
    IO.inspect Sample2.find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "c" end)
    IO.inspect Sample2.find_indexes(["a", "b", "c", "b", "b"], fn(x) -> x == "b" end)
    

    Executed as follows,

    % elixir find.ex
    Sample1
    [0]
    [2]
    [1, 3, 4]
    Sample2
    [0]
    [2]
    [1, 3, 4]