Wie überprüfe ich, ob ein Gegenstand in einer Elixierliste oder einem Tupel vorhanden ist?

83

Dies ist scheinbar einfach, aber ich kann es nicht in den Dokumenten finden. Ich muss einfach zurückkehren trueoder falsewenn ein Element in einer Liste oder einem Tupel vorhanden ist. Ist das Enum.find/3wirklich der beste Weg, dies zu tun?

Enum.find(["foo", "bar"], &(&1 == "foo")) != nil
ewH
quelle
2
Für eine Liste könnte ich sehen, wo Sie nur sehen möchten, ob der Artikel dort ist, in dem Enum.member? / 2 eine gute wäre. Aber für ein Tupel interessiert Sie normalerweise die Position des Wertes, das ist eine der Schönheiten von Tupeln ... Vielleicht möchten Sie die Verwendung eines Tupels in Betracht ziehen, wenn Sie sich nicht für die Position
interessieren
Möglicherweise möchten Sie die Antwort von @ Gazler als akzeptierte Antwort markieren, wenn sie richtig ist.
Onorio Catenacci
1
Kurzer Hinweis zur Leistung. Der x in yGuard ist sehr performant, da er zur Kompilierungszeit unterschiedliche Funktionsdefinitionen erstellt. Zur Laufzeit ist es weniger performant, entspricht Enum.member?, obwohl sie für kleine n in Ordnung sind . Bei großen n und engen Schleifen erzielen Sie eine bessere Leistung durch Hashes wie z MapSet.member?. Aber in den meisten Fällen x in yund Enum.member?sind in Ordnung!
Dennis

Antworten:

125

Sie können verwenden Enum.member?/2

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

Mit einem Tupel möchten Sie zuerst mit in eine Liste konvertieren Tuple.to_list/1

Tuple.to_list({"foo", "bar"})
# ["foo", "bar"]
Gazler
quelle
Danke Gazler. Ihre Antwort ist korrekt, aber ich wollte eine separate Antwort veröffentlichen, die auf allen Vorschlägen basiert, die ich in der Community erhalten habe.
ewH
Beachten Sie, dass Sie nicht in der Lage sind, Enum.member?/2innerhalb einer Wache zu verwenden. In diesem Fall müssen Sie sich verlassen in. Zum Beispiel : def foo(string) when string in ["one", "two"], do: IO.puts(string). Das ist übrigens lustig, denn es inhandelt sich um ein Makro, das übersetzt wird in Enum.member?/2: D
Alessandro
39

Basierend auf den Antworten hier und in Elixir Slack gibt es mehrere Möglichkeiten, um zu überprüfen, ob ein Element in einer Liste vorhanden ist. Per Antwort von @Gazler:

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

oder einfach

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

oder

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

oder wenn Sie den Artikel anstelle von trueoder suchen und zurückgeben möchtenfalse

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

Wenn Sie ein Tupel überprüfen möchten, müssen Sie es in eine Liste konvertieren (credit @Gazler):

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

Aber wie @CaptChrisD in den Kommentaren hervorhob, ist dies eine ungewöhnliche Notwendigkeit für ein Tupel, da man sich normalerweise um die genaue Position des Elements in einem Tupel für den Mustervergleich kümmert.

ewH
quelle
26

Oder verwenden Sie einfach in:

iex(1)> "foo" in ["foo", "bar"]
true
iex(2)> "foo" in Tuple.to_list({"foo", "bar"})
true
Slashmili
quelle
Diese Antwort ist wie die einzige, die die Frage von OP beantwortet: "... existiert in einer Elixierliste" ... keine Aufzählung.
Daniel Lizik
2

Ich habe gestern mit dem Programmieren in Elixir begonnen, aber ich werde etwas ausprobieren, das ich viel in JS gemacht habe. Vielleicht ist es nützlich, wenn die Liste viele Elemente enthält und Sie sie nicht die ganze Zeit mit Enum.member durchlaufen möchten.

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

Sie können auch eine Kreuzung mit einer anderen Liste abrufen:

Enum.filter(some_other_list,&(map_existence[&1]))
Johel Carvalho
quelle
1

Sie können auch verwenden 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
Sabit Huraira
quelle