【问题标题】:Find indexes from list in Elixir从 Elixir 的列表中查找索引
【发布时间】:2018-11-22 04:27:23
【问题描述】:

使用Enum.find_index/2,我们可以找到一个元素的索引。 但是,如果同一个元素多次出现,我们怎么办呢?

我希望有这种行为:

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]

感谢您的任何想法。

【问题讨论】:

    标签: arrays functional-programming elixir


    【解决方案1】:

    我在库中找不到确切的函数,所以尝试实现它。希望对大家有所帮助。

    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)
    

    如下执行,

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

    【讨论】:

    • 感谢您的帮助@parroty!我们也可以这样做:Enum.with_index(["a", "b", "c", "b", "b"]) |> Enum.filter_map(fn {x, _} -> x == "b" end, fn {_, i} -> i end)
    • 是的。这会更像灵丹妙药。
    【解决方案2】:

    或者,您可以使用0..length(list) 范围压缩列表并使用新项目过滤列表:

    line = IO.read(:stdio, :all) 
    |> String.split
    |> Enum.zip(0..100)
    |> Enum.filter(fn({_, x}) -> rem(x, 2) != 0 end)
    |> Enum.map(fn({x, _}) -> "#{x}\n" end)
    

    从标准输入过滤给定列表中的奇数元素。

    请注意,范围 (0..100) 中的 100 必须是列表的长度。我假设我有一个包含 100 个项目的列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-16
      • 1970-01-01
      • 2019-05-27
      • 1970-01-01
      相关资源
      最近更新 更多