如何解决如果没有,
我目前正在尝试遍历Mongo的一个收藏集。为此,我正在使用此正则表达式过滤该集合。在某些情况下,正则表达式返回nil,在这种情况下它会破坏List.first
,因为列表中没有内容。稍后会导致问题。
我来自Ruby,在那里我可以做next unless recipient
或使用孤独的运算符List&.first
到那里去。我如何才能在Elixir中做到这一点?如果接收者的值为nil,我主要想跳过当前迭代。
recipient =
Regex.run(~r/(?<=recipient-).+\/*/,engagement["_id"])
|> List.first()
|> String.split("/")
|> List.first()
解决方法
如果我对您的理解正确,则似乎您需要开始使用case
块,例如:
case Regex.run(~r/(?<=recipient-).+\/*/,engagement["_id"]) do
nil -> IO.puts "Skip List.first for Regex.run"
out -> out |> List.first |> String.split("/") |> List.first
end
OR
Regex.run(~r/(?<=recipient-).+\/*/,engagement["_id"]) |>
case do
nil -> IO.puts "Skip List.first for Regex.run"
out -> out |> List.first |> String.split("/") |> List.first
end
,
作为case语句的替代方法,您可以使用function子句的开头来匹配正则表达式的结果,即nil
或match:
defmodule A do
def go() do
Enum.each(["a/x","c","b/x"],fn str ->
Regex.run(~r{(a|b)/x},str,capture: :first)
|> handle_recipient
end)
end
defp handle_recipient(nil),do: :no_match #does nothing
defp handle_recipient([match]) do
match
|> String.split("/")
|> List.first()
|> IO.inspect()
end
end
在iex中:
~/elixir_programs$ iex "a.ex"
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> A.go
"a"
"b"
:ok
iex(2)>
听起来您可能想使用Enum.reduce/3来过滤您的收藏集:
defmodule A do
def go() do
Enum.reduce(["a/x",[],fn str,acc ->
Regex.run(~r{(a|b)/*},capture: :first)
|> handle_recipient(acc)
end)
end
defp handle_recipient(nil,acc),do: acc
defp handle_recipient([match],acc) do
result = match
|> String.split("/")
|> List.first
[result|acc]
end
end
在iex中:
~/elixir_programs$ iex "a.ex"
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> A.go
["b","a"]
您也可以使用for来写:
defmodule A do
def go() do
for str <- ["a/x",reduce: [] do
acc -> Regex.run(~r{(a|b)/x},capture: :first)
|> handle_recipient(acc)
end
end
defp handle_recipient(nil,do: acc
defp handle_recipient([match],acc) do
result = match
|> String.split("/")
|> List.first()
[result|acc]
end
end
,
TL; DR 使用for/1
理解可过滤掉不需要的输入(不是列表的所有内容,具有二进制头)
recipient =
for [match | _] when is_binary(match) <-
Regex.run(~r/(?<=recipient-).+\/*/,engagement["_id"]),do: match |> String.split("/") |> List.first()
根据Regex.run/3
的文档,它返回类型
nil | [binary()] | [{integer(),integer()}]
也就是说,人们可能会使用List.wrap/1
从nil
中产生一个空列表。
recipient =
~r/(?<=recipient-).+\/*/
|> Regex.run(engagement["_id"])
|> List.wrap()
|> List.first()
|> String.split("/")
|> List.first()
不幸的是,它随后会在管道上String.split/2
爆炸。
也就是说,人们可能会求助于Regex.scan/3
而不是{em}总是返回列表的Regex.run/3
。
recipient =
~r/(?<=recipient-).+\/*/
|> Regex.scan(engagement["_id"])
|> List.first()
|> List.first() # to get to the first capture
|> String.split("/")
|> List.first()
但是所有这些看起来像是XY问题。你说
如果接收者的值为
nil
,我主要希望跳过当前迭代。
这是不可能的,但是有很多解决方法。
-
Enum.reduce/3
,带有带有两个子句的化简器 -
Enum.map/2
后跟Enum.reject/2
-
for/1
理解过滤出nil
s
我会为后者投票。
recipient =
for [match | _] when is_binary(match) <- Regex.run(~r/(?<=recipient-).+\/*/,do: match |> String.split("/") |> List.first()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。