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


85

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

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

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 в комментариях, это необычная потребность в кортеже, потому что обычно для сопоставления с образцом заботится о точном положении элемента в кортеже.


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]))

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.