Jak sprawdzić, czy przedmiot znajduje się na liście lub krotce Elixir?

85

Pozornie jest to proste, ale nie mogę znaleźć tego w dokumentacji. Muszę po prostu zwrócić truelub falsejeśli element istnieje na liście lub w krotce. Czy Enum.find/3naprawdę jest to najlepszy sposób?

Enum.find(["foo", "bar"], &(&1 == "foo")) != nil
ewH
źródło
2
Aby uzyskać listę, mogę zobaczyć, gdzie chcesz po prostu sprawdzić, czy jest tam element, w którym Enum.member? / 2 byłby dobry. Ale za krotki zwykle dbają o pozycji wartości, który jest jednym z uroków krotki ... może warto rozważyć wykorzystanie krotki jeśli nie dbają o położeniu
CaptChrisD
Możesz oznaczyć odpowiedź @ Gazler jako zaakceptowaną, jeśli jest poprawna.
Onorio Catenacci
1
Krótka notatka o wydajności. x in yStrażnik jest bardzo wydajnych, ponieważ tworzy różne definicje funkcji w czasie kompilacji. W czasie wykonywania jest mniej wydajny, równoważny Enum.member?, chociaż można ich używać w przypadku małych n . Dla dużych n i ciasne pętle, dostaniesz lepszą wydajność od czegoś, mieszań, takie jak MapSet.member?. Ale w większości przypadków x in yi Enum.member?są w porządku!
Dennis

Odpowiedzi:

130

Możesz użyć Enum.member?/2

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

W przypadku krotki będziesz chciał najpierw przekonwertować na listę za pomocą Tuple.to_list/1

Tuple.to_list({"foo", "bar"})
# ["foo", "bar"]
Gazler
źródło
Dzięki, Gazler. Twoja odpowiedź jest poprawna, ale chciałem zamieścić osobną odpowiedź na podstawie wszystkich sugestii, które otrzymałem od społeczności.
ewH,
Zauważ, że nie będziesz mógł używać Enum.member?/2wewnątrz strażnika. W takim przypadku będziesz musiał polegać in. Na przykład: def foo(string) when string in ["one", "two"], do: IO.puts(string). Nawiasem mówiąc, jest to zabawne, ponieważ injest to makro, które można przetłumaczyć na Enum.member?/2: D
Alessandro
39

W oparciu o odpowiedzi tutaj oraz w Elixir Slack, istnieje wiele sposobów sprawdzenia, czy pozycja znajduje się na liście. Za odpowiedź od @Gazler:

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

lub po prostu

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

lub

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

lub jeśli chcesz znaleźć i zwrócić przedmiot zamiast truelubfalse

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

Jeśli chcesz sprawdzić krotkę, musisz przekonwertować na listę (kredyt @Gazler):

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

Ale jak @CaptChrisD zauważył w komentarzach, jest to rzadka potrzeba tworzenia krotki, ponieważ zwykle zależy nam na dokładnym położeniu elementu w krotce w celu dopasowania wzorca.

ewH
źródło
26

Lub po prostu użyj in:

iex(1)> "foo" in ["foo", "bar"]
true
iex(2)> "foo" in Tuple.to_list({"foo", "bar"})
true
slashmili
źródło
Ta odpowiedź jest jedyną, która odpowiada na pytanie OP: „... istnieje w LIŚCIE eliksirów” ... a nie wyliczenie.
Daniel Lizik,
2

Wczoraj zacząłem programować w Elixirze, ale spróbuję czegoś, co robiłem dużo w JS, może jest to przydatne, gdy lista ma dużo elementów i nie chcesz jej cały czas przemierzać za pomocą Enum.member?

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

Możesz również pobrać skrzyżowanie z inną listą:

Enum.filter(some_other_list,&(map_existence[&1]))
Johel Carvalho
źródło
1

Możesz Enum.find_value/3też użyć :

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
Sabit Huraira
źródło