Làm cách nào để kiểm tra xem một mục có tồn tại trong danh sách hoặc bộ Elixir không?


83

Điều này có vẻ đơn giản, nhưng tôi dường như không thể tìm thấy nó trong tài liệu. Tôi chỉ cần trả lại truehoặc falsenếu một mục tồn tại trong danh sách hoặc bộ giá trị. Là Enum.find/3thực sự là cách tốt nhất để làm điều này?

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

2
Đối với một danh sách, tôi có thể xem nơi bạn muốn chỉ xem liệu mục đó có ở đó hay không, trong đó Enum.member? / 2 sẽ là một lựa chọn tốt. Nhưng đối với một tuple bạn thường quan tâm đến vị trí của các giá trị, đó là một trong những nét đẹp của các bộ ... có thể muốn xem xét việc sử dụng một tuple nếu bạn không quan tâm đến vị trí
CaptChrisD

Bạn có thể đánh dấu câu trả lời của @ Gazler là câu trả lời được chấp nhận nếu nó đúng.
Onorio Catenacci

1
Ghi chú nhanh về hiệu suất. Trình x in ybảo vệ rất hiệu quả vì nó tạo ra các định nghĩa chức năng khác nhau tại thời điểm biên dịch. Trong thời gian chạy, nó kém hiệu suất hơn, tương đương với Enum.member?, mặc dù chúng tốt để sử dụng cho n nhỏ . Đối với n lớn và vòng lặp chặt chẽ, bạn sẽ nhận được hiệu suất tốt hơn từ thứ gì đó có hàm băm, chẳng hạn như MapSet.member?. Nhưng trong hầu hết các trường hợp, x in yEnum.member?ổn!
Dennis

Câu trả lời:


125

Bạn có thể dùng Enum.member?/2

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

Với một tuple, bạn sẽ muốn chuyển đổi thành một danh sách trước tiên bằng cách sử dụng Tuple.to_list/1

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

Cảm ơn Gazler. Câu trả lời của bạn là đúng, nhưng tôi muốn đăng một câu trả lời riêng dựa trên tất cả các đề xuất mà tôi nhận được trên cộng đồng.
ewH

Lưu ý rằng bạn sẽ không thể sử dụng Enum.member?/2bên trong một người bảo vệ. Trong trường hợp đó, bạn sẽ phải dựa vào in. Ví dụ: def foo(string) when string in ["one", "two"], do: IO.puts(string). Bằng cách này, đây là buồn cười, vì inlà một macro mà dịch để Enum.member?/2: D
Alessandro

39

Dựa trên các câu trả lời ở đây và trong Elixir Slack, có nhiều cách để kiểm tra xem một mục có tồn tại trong danh sách hay không. Theo câu trả lời của @Gazler:

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

hoặc đơn giản

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

hoặc là

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

hoặc nếu bạn muốn tìm và trả lại mặt hàng thay vì truehoặcfalse

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

Nếu bạn muốn kiểm tra một tuple, bạn cần chuyển đổi sang danh sách (tín dụng @Gazler):

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

Nhưng như @CaptChrisD đã chỉ ra trong các nhận xét, đây là một nhu cầu không phổ biến đối với một bộ tuple vì người ta thường quan tâm đến vị trí chính xác của mục trong một bộ tuple để khớp mẫu.


26

Hoặc chỉ sử dụng in:

iex(1)> "foo" in ["foo", "bar"]
true
iex(2)> "foo" in Tuple.to_list({"foo", "bar"})
true

Câu trả lời này giống như câu trả lời duy nhất trả lời câu hỏi của OP: "... tồn tại trong một DANH SÁCH thuốc tiên" ... không phải là một enum.
Daniel Lizik

2

Tôi đã bắt đầu lập trình trong Elixir ngày hôm qua, nhưng tôi sẽ thử một cái gì đó mà tôi đã làm rất nhiều trong JS, có lẽ nó hữu ích khi danh sách có rất nhiều phần tử và bạn không muốn xem qua nó mọi lúc bằng Enum.member?

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

Bạn cũng có thể truy xuất một giao lộ với một số danh sách khác:

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

1

Bạn cũng có thể sử dụng 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.