我对Erlang比较新,我有一个类似#{“a/.+":“v1”,“B/c/.+"的Map:“v2”}我想通过输入键“a/d”来匹配“a/.+”并获得“v1”。当键是正整数,输入键是正则表达式时,很容易模式化,我如何实现它呢?
afdcj2ne1#
对于这种情况,不必须使用map。其思想是使用regex来查找与输入匹配的键,然后返回Map的值。未优化版本使用re:run/2,而不编译模式。
map
re:run/2
L1 = [{"a/.+", "v1"}, {"b/c/.+", "v2"}],LResult1 = lists:foldl(fun({K, V}, ListIn) -> Match = re:run("a/d", K), case Match of nomatch -> ListIn; _ -> ListIn ++ [{K, V}] end end, [], L1 ),case LResult1 of [] -> no_matching_rule; _ -> Hd1 = hd(LResult1), {K1, V1} = Hd1, V1end.
L1 = [{"a/.+", "v1"}, {"b/c/.+", "v2"}],
LResult1 = lists:foldl(fun({K, V}, ListIn) ->
Match = re:run("a/d", K),
case Match of
nomatch -> ListIn;
_ -> ListIn ++ [{K, V}]
end
end,
[],
L1
),
case LResult1 of
[] ->
no_matching_rule;
_ ->
Hd1 = hd(LResult1),
{K1, V1} = Hd1,
V1
end.
优化版本可以通过在使用之前编译一次regex模式来实现。
{ok, Mp1} = re:compile("a/.+"),{ok, Mp2} = re:compile("b/c/.+"),L2 = [{Mp1, "v1"}, {Mp2, "v2"}],LResult2 = lists:foldl(fun({K, V}, ListIn) -> Match = re:run("a/d", K), case Match of nomatch -> ListIn; _ -> ListIn ++ [{K, V}] end end, [], L2 ),case LResult2 of [] -> no_matching_rule; _ -> Hd2 = hd(LResult2), {K2, V2} = Hd2, V2end.
{ok, Mp1} = re:compile("a/.+"),
{ok, Mp2} = re:compile("b/c/.+"),
L2 = [{Mp1, "v1"}, {Mp2, "v2"}],
LResult2 = lists:foldl(fun({K, V}, ListIn) ->
L2
case LResult2 of
Hd2 = hd(LResult2),
{K2, V2} = Hd2,
V2
在Erlang shell中粘贴以上任何代码都将生成"v1"。上面的代码假设一个输入可以有多个匹配的模式,但是只有第一个模式会作为输出输出。
"v1"
z31licg02#
If you want to find all the keys in the map that match your string, you will need to iterate over the whole map:a.erl:
-module(a).-compile(export_all).find(String, Map) -> MyMatchFun = fun (RegexKey, Val, Acc) -> case re:run(String, RegexKey) of nomatch -> Acc; {match, _} -> [Val | Acc] end end, maps:fold(MyMatchFun, _Acc=[], Map).
-module(a).
-compile(export_all).
find(String, Map) ->
MyMatchFun = fun (RegexKey, Val, Acc) ->
case re:run(String, RegexKey) of
nomatch -> Acc;
{match, _} -> [Val | Acc]
maps:fold(MyMatchFun, _Acc=[], Map).
In the shell:
34> c(a). a.erl:2:2: Warning: export_all flag enabled - all functions will be exported% 2| -compile(export_all).% | ^{ok,a}35> Map.#{"a/.+" => "v1","a/b/.+" => "v3","b/c/.+" => "v2"}36> a:find("a/d", Map).["v1"]36> a:find("b/c/dd", Map).["v2"]38> a:find("a/b/cc", Map).["v3","v1"]
34> c(a).
a.erl:2:2: Warning: export_all flag enabled - all functions will be exported
% 2| -compile(export_all).
% | ^
{ok,a}
35> Map.
#{"a/.+" => "v1","a/b/.+" => "v3","b/c/.+" => "v2"}
36> a:find("a/d", Map).
["v1"]
36> a:find("b/c/dd", Map).
["v2"]
38> a:find("a/b/cc", Map).
["v3","v1"]
If there is only one key in the map that will match your string, then you can stop iterating over the map as soon as you find a match:a.erl:
-module(a).-compile(export_all).find(String, Map) -> I = maps:iterator(Map), match_for(String, I).match_for(String, I) -> case maps:next(I) of none -> %% then you have reached the end of the Map no_keys_in_map_matched_string; {RegExKey, Val, NewI} -> case re:run(String, RegExKey) of nomatch -> match_for(String, NewI); %% continue iterating over the Map looking for a match {match, _} -> Val %% found a match, so return the associated value end end.
I = maps:iterator(Map),
match_for(String, I).
match_for(String, I) ->
case maps:next(I) of
none -> %% then you have reached the end of the Map
no_keys_in_map_matched_string;
{RegExKey, Val, NewI} ->
case re:run(String, RegExKey) of
nomatch -> match_for(String, NewI); %% continue iterating over the Map looking for a match
{match, _} -> Val %% found a match, so return the associated value
27> c(a). a.erl:2:2: Warning: export_all flag enabled - all functions will be exported% 2| -compile(export_all).% | ^{ok,a}28> Map = #{"a/.+" => "v1", "b/c/.+" => "v2"}.29> a:find("a/d", Map). "v1"30> a:find("a/b/cc", Map)."v1"31> a:find("b/c/dd", Map)."v2"32> a:find("z", Map). no_keys_in_map_matched_string
27> c(a).
28> Map = #{"a/.+" => "v1", "b/c/.+" => "v2"}.
29> a:find("a/d", Map).
30> a:find("a/b/cc", Map).
31> a:find("b/c/dd", Map).
"v2"
32> a:find("z", Map).
no_keys_in_map_matched_string
2条答案
按热度按时间afdcj2ne1#
对于这种情况,不必须使用
map
。其思想是使用regex来查找与输入匹配的键,然后返回Map的值。未优化版本使用re:run/2
,而不编译模式。优化版本可以通过在使用之前编译一次regex模式来实现。
在Erlang shell中粘贴以上任何代码都将生成
"v1"
。上面的代码假设一个输入可以有多个匹配的模式,但是只有第一个模式会作为输出输出。
z31licg02#
If you want to find all the keys in the map that match your string, you will need to iterate over the whole map:
a.erl:
In the shell:
If there is only one key in the map that will match your string, then you can stop iterating over the map as soon as you find a match:
a.erl:
In the shell: