我需要通过函数管道一个字符串列表来返回一个字符串。目前,我有这个:
@tag_delimiters [" ", "(", ".", "#"]
def tag(string) do
tag(string, " ")
|> tag("(")
|> tag(".")
|> tag("#")
end
defp tag(string, delimiter)
[head | _] = String.split(string, delimiter)
head
end
我想删除管道并使用某种递归函数来基于@tag_delimiter
属性运行它。递归管道的正确方法是什么?
编辑DSL:
tag(string)
Feed "span(class="foo")#bar Hello my name is Dex"
或"span Hello my name is Dex"
时,我希望输出为"span"
。我这样做是递归地寻找成功的第一个单词的字符。但是,我通过使用分隔符分割字符串来实现此目的。
这已经有效了,我只是想找一个更优雅的解决方案来解决我的管道问题。
答案 0 :(得分:1)
您可以使用Enum.reduce
功能执行此操作。
Enum.reduce(@tag_delimiters, string, fn(a, b) -> tag(b, a) end)
答案 1 :(得分:0)
如果我了解您的需求,您可以使用String.split
函数并调整模式以正确地标记输入字符串。
具体来说,您可以传递要用作模式的字符列表。实际上,您可以直接提供@tag_dividers
。这是一个可能的例子:
defmodule Tags do
@dividers [" ", "(", ".", "#"]
def split(string) do
List.first(String.split(string, @dividers, parts: 2))
end
end
我使用String.split
将分隔符作为列表传递。我还强制该函数只将输入分成两个标记(最多):标记和其余标记。
string = ~s{span(class="foo")#bar Hello my name is Dex}
String.split(string, [" ", "(", "."], parts: 2)
# => ["span", "class=\"foo\")#bar Hello my name is Dex"]
然后我使用List.first
返回结果中的第一项。当然,我可以使用匹配[head|_]
的模式并返回head
,但是如果split
返回一个空列表,我将不得不处理结果不匹配的情况模式。
在这种情况下,此功能只会返回nil
。
Tags.split(~s{span(class="foo")#bar Hello my name is Dex})
# => "span"