如何解决从复杂的元组/列表结构创建有效的函数声明
| 给定Erlang中的一个复杂对象,是否有一种通用的方法可以为它提供一个有效的函数声明,而不是盯着它呢?我正在维护以前由巨型结构的忠实拥护者编写的一些代码,事实证明,手动进行操作很容易出错。 我本身不需要迭代整个过程,只需抓住顶层即可。 例如,我现在正在研究这个-[[[\"SIP\",47,\"2\",46,\"0\"],32,\"407\",\"Proxy Authentication Required\",\"\\r\\n\"],[{\'Via\',[{\'via-parm\',{\'sent-protocol\',\"SIP\",\"2.0\",\"UDP\"},{\'sent-by\',\"172.20.10.5\",\"5060\"},[{\'via-branch\',\"z9hG4bKb561e4f03a40c4439ba375b2ac3c9f91.0\"}]}]},{\'Via\',\"172.20.10.15\",\"12dee0b2f48309f40b7857b9c73be9ac\"}]}]},{\'From\',{\'from-spec\',{\'name-addr\',[[]],{\'SIP-URI\',[{userinfo,{user,\"003018CFE4EF\"},[]}],{hostport,\"172.20.10.11\",[]},{\'uri-parameters\',[]}},[{tag,\"b7226ffa86c46af7bf6e32969ad16940\"}]}},{\'To\',\"3966\"},\"a830c764\"}]},{\'Call-ID\',\"90df0e4968c9a4545a009b1adf268605@172.20.10.15\"},{\'CSeq\',1358286,\"SUBSCRIBE\"},[\"date\",\'HCOLON\',[\"Mon\",44,[\"13\",\"Jun\",\"2011\"],[\"17\",58,\"03\",\"55\"],\"GMT\"]],{\'Contact\',[[{\'name-addr\',\"3ComCallProcessor\"},[]],[]]},[\"expires\",3600],[\"user-agent\",[\"3Com\",[[\'LWS\',[\"VCX\",[]]],[\'LWS\',[\"7210\",[\"IP\",[\"CallProcessor\",[[\'SLASH\',\"v10.0.8\"]]]]]],[\"proxy-authenticate\",[\"Digest\",\'LWS\',[\"realm\",\'EQUAL\',[\'SWS\',34,\"3Com\",34]],[[\'COMMA\',[\"domain\",34]]],[\'COMMA\',[\"nonce\",\"btbvbsbzbBbAbwbybvbxbCbtbzbubqbubsbqbtbsbqbtbxbCbxbsbybs\",[\"stale\",\"FALSE\"]],[\"algorithm\",\"MD5\"]]]]],{\'Content-Length\',0}],\"\\r\\n\",[\"\\n\"]]
解决方法
我注意到您的澄清评论。我希望自己添加一条评论,但没有足够的业力。无论如何,我为此使用的技巧是在Shell中进行实验。我将针对样本数据结构进行迭代,直到找到最简单的形式。您可以使用_ match-all变量。我在emacs shell窗口中使用erlang shell。
首先,将样本绑定到变量:
A = [{{a,b},[{c,d},{e,f}]]。
现在针对变量设置原始结构:
[{a,b},[{c,d},{e,f}]] =A。
如果您按Enter键,则会看到它们匹配。按alt-p(忘记emacs所谓的alt,但在我的键盘上是alt),以返回上一行。用下划线替换一些元组或列表项:
[_,[{c,d},{e,f}]]。
按Enter键以确保您做对了并且它们仍然匹配。这个示例很简单,但是对于深度嵌套的多线结构而言,它比较棘手,因此能够快速进行匹配以方便测试。有时候,您可能想猜测一下整个范围,例如使用下划线将元组列表中的元组列表匹配,该元组是列表的第三个元素。如果放置正确,则可以一次匹配整个内容,但很容易误读。
无论如何,重复一下以探索结构的基本形状并将实变量放在要提取值的位置:
[_,[_,_]] =A。
[_,_] =A。
[_,MyTupleList] = A。%%让我们获取此元组列表
[{MyAtom,b},[{c,d},MyTuple]] = A. %%,或者我们想要这个原子和元组
这就是我高效剖析和匹配复杂数据结构的方式。
但是,我不知道你在做什么。我倾向于拥有一个使用KVC的包装函数,以准确提取所需的内容,然后从那里为每种类型的结构分发给辅助函数。
, 也许https://github.com/etrepum/kvc
, 如果我对您的理解正确,那么您想对某些未知格式的大型数据结构进行模式匹配。
例:
Input: {a,b} {a,b,c,d} {a,[],{},{b,c}}
function({A,B}) -> do_something;
function({A,B,C,D}) when is_atom(B) -> do_something_else;
function({A,D}) when is_list(B) -> more_doing.
通用答案当然是,仅凭数据就无法确定如何对数据进行分类是不确定的。
首先,您可能应该了解iolist。它们是由io_lib:format / 2之类的函数创建的,并且在代码中的许多其他地方也创建了它们。
一个例子是
[[\"SIP\",47,\"2\",46,\"0\"],32,\"407\",\"Proxy Authentication Required\",\"\\r\\n\"]
将打印为
SIP/2.0 407 Proxy Authentication Required
因此,我将从使用以下功能展平所有这些列表开始
flatten_io(List) when is_list(List) ->
Flat = lists:map(fun flatten_io/1,List),maybe_flatten(Flat);
flatten_io(Tuple) when is_tuple(Tuple) ->
list_to_tuple([flatten_io(Element) || Element <- tuple_to_list(Tuple)];
flatten_io(Other) -> Other.
maybe_flatten(L) when is_list(L) ->
case lists:all(fun(Ch) when Ch > 0 andalso Ch < 256 -> true;
(List) when is_list(List) ->
lists:all(fun(X) -> X > 0 andalso X < 256 end,List);
(_) -> false
end,L) of
true -> lists:flatten(L);
false -> L
end.
(注意:完全未经测试且效率很低。如果列表不正确,也会崩溃,但是无论如何您都不应该在数据结构中包含这些。)
再三考虑,我无能为力。字符串中使用原子\'COMMA \'作为逗号的任何数据结构都应该被取出并射击。
您还应该能够弄平这些东西,并开始了解您所看到的内容。
我知道这不是一个完整的答案。希望能帮助到你。
,很难推荐一些处理方法。
以更合理,更最小的格式转换所有结构看起来是值得的。这主要取决于这些结构的相似性。
除了必须为100个功能中的每个功能提供特殊功能之外,还必须要有一些自动重新格式化的功能,甚至可以将零件记录下来。
一旦有了记录,它就很容易为它编写函数,因为您不需要知道记录中元素的实际数量。更重要的是:当元素数量改变时,您的代码不会中断。
总结:通过某种方式用最通用的代码清除它们,从而在代码和这些结构的混乱之间建立了一个障碍。这可能是通用重新格式化与结构特定的东西的混合。
作为在该结构中已经可见的示例:\'name-addr\'
元组看起来像它们具有统一的结构。因此,您可以递归遍历您的结构(遍历元组和列表的所有元素),并匹配具有“ѭ5”之类通用结构的“事物”,并将其替换为漂亮的记录。
为了帮助您眼球,您可以按照以下示例编写自己的辅助函数:
eyeball(List) when is_list(List) ->
io:format(\"List with length ~b\\n\",[length(List)]);
eyeball(Tuple) when is_tuple(Tuple) ->
io:format(\"Tuple with ~b elements\\n\",[tuple_size(Tuple)]).
因此,您将获得如下输出:
2> eyeball({a,c}).
Tuple with 3 elements
ok
3> eyeball([a,c]).
List with length 3
ok
将此扩展为有用的工具供您使用。您可以通过递归元素并缩进输出来处理多个级别。
, 使用模式匹配和适用于列表的功能仅提取您需要的内容。
查看http://www.erlang.org/doc/man/lists.html:
keyfind
,keyreplace
,L = [H|T]
,...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。