Как проверить, существует ли элемент в списке или кортеже Эликсира?

85

Это вроде бы просто, но я не могу найти его в документации. Мне нужно просто вернуть trueили, falseесли элемент существует в списке или кортеже. Действительно Enum.find/3ли лучший способ сделать это?

Enum.find(["foo", "bar"], &(&1 == "foo")) != nil
ewH
источник
2
Для списка я мог бы увидеть, где вы хотите просто увидеть, есть ли там элемент, в котором Enum.member? / 2 был бы хорошим. Но для кортежа вас обычно заботит положение значения, это одна из прелестей кортежей ... возможно, вы захотите рассмотреть возможность использования кортежа, если вам не
важна
Вы можете отметить ответ @Gazler как принятый, если он правильный.
Онорио Катеначчи
1
Краткое примечание о производительности. x in yОхранник очень производительный , потому что он создает различные определения функций во время компиляции. Во время выполнения он менее эффективен, эквивалентен Enum.member?, хотя их можно использовать для малых n . Для больших n и плотных циклов вы получите лучшую производительность от чего-то, что имеет хеширование, например MapSet.member?. Но в большинстве случаев x in yи Enum.member?все нормально!
Деннис

Ответы:

130

Вы можете использовать Enum.member?/2

Enum.member?(["foo", "bar"], "foo")
# true

С кортежем вы захотите сначала преобразовать его в список, используя Tuple.to_list/1

Tuple.to_list({"foo", "bar"})
# ["foo", "bar"]
Газлер
источник
Спасибо, Газлер. Ваш ответ правильный, но я хотел опубликовать отдельный ответ, основанный на всех предложениях, которые я получил от сообщества.
ewH 05
Обратите внимание, что вы не сможете использовать Enum.member?/2внутри охранника. В этом случае придется положиться на in. Например: def foo(string) when string in ["one", "two"], do: IO.puts(string). Между прочим, это забавно, потому что inэто макрос, который переводится как Enum.member?/2: D
Алессандро
39

Основываясь на ответах здесь и в Elixir Slack, есть несколько способов проверить, существует ли элемент в списке. Согласно ответу @Gazler:

Enum.member?(["foo", "bar"], "foo")
# true

или просто

"foo" in ["foo", "bar"]
# true

или же

Enum.any?(["foo", "bar"], &(&1 == "foo")
# true

или если вы хотите найти и вернуть товар вместо trueилиfalse

Enum.find(["foo", "bar"], &(&1 == "foo")
# "foo"

Если вы хотите проверить кортеж, вам нужно преобразовать его в список (кредит @Gazler):

Tuple.to_list({"foo", "bar"})
# ["foo", "bar"]

Но, как отметил @CaptChrisD в комментариях, это необычная потребность в кортеже, потому что обычно для сопоставления с образцом заботится о точном положении элемента в кортеже.

ewH
источник
26

Или просто используйте in:

iex(1)> "foo" in ["foo", "bar"]
true
iex(2)> "foo" in Tuple.to_list({"foo", "bar"})
true
Слашмили
источник
Этот ответ похож на единственный, который отвечает на вопрос OP: «... существует в СПИСКЕ эликсиров» ... не в перечислении.
Даниэль Лизик
2

Вчера я начал программировать на Elixir, но я попробую то, что много делал на JS. Может быть, это полезно, когда в списке много элементов, и вы не хотите постоянно перемещаться по нему с помощью Enum.member?

map_existence = Enum.reduce(list,%{}, &(Map.put(&2,&1,true)))
map_existence[item_to_check]

Вы также можете получить пересечение с другим списком:

Enum.filter(some_other_list,&(map_existence[&1]))
Йохель Карвалью
источник
1

Вы также можете использовать Enum.find_value/3:

iex(1)> Enum.find_value(["foo", "bar"],false, fn(x)-> x=="foo" end)
true

iex(2)> Enum.find_value(["foo", "bar"],false, fn(x)-> x=="food" end)
false
Сабит Хурайра
источник