摆脱列表中的元组,erlang
get rid of tuple in list, erlang
我想删除列表中的所有元组,例如
我有这样的输入
test:stack({push, [{{mul,{plus,{num,2},{num,3}},{num,4}},[]}]}, []).
%% note: (returns wrong output because of the multiple tuples brackets)
如果我有这样的东西:
proj:stack({push, [mul,plus,{num,2},{num,3},{num,4}]}, []).
%% this would return:
%% [{push,{num,4}},{push,{num,3}},{push,{num,2}},
%% {push,plus},{push,mul}]
%% This is near to what I need.
我的代码是这样的:
stack({push, []}, StackList) -> StackList;
stack({push,[H|T]}, StackList) ->
stack({push, T}, [{push,H} | StackList]).
我想实现这样的目标:
{push, {num, 4}}, {push, {num, 3}},
{push, {num, 2}}, {add}, {mul}, {pop}, {ret}
我想过使用过滤器来实现这一点,但也许是其他原因?
这是您拥有的代码:
lists:filter(fun(E) -> E /= {} end, list1)
这不会从列表中过滤掉所有元组。这只会过滤掉等于空元组 {} 的列表元素。如果你想要一个从列表中过滤元组的函数,你应该用 not 和 is_tuple/1 BIF:
替换 lambda 表达式中的 E /= {} 谓词
not is_tuple(E)
我对你最初的问题也有点困惑。你说
list1= [{1},{2},{3}] 我想要它作为 list1 = [1,2,3]
这让我觉得您想映射列表并将列表中的每个单个元素元组转换为其内容。如果这是您想要的行为,请使用 map/2 BIF 或列表理解。
[ E || {E} <- list1]
这个表达式读作,"for each single element tuple in list1, generate a new list whose elements are the contents of those tuples."
希望这对您有所帮助。享受 Erlang。
太大,无法发表评论。嗯...
这看起来很像您正在尝试构建一台堆栈计算机,在本例中可能是一个计算器。有一个 good RPN example walkthrough in LYSE 我强烈推荐你看一看。它不涉及此特定语法,但它演示了如何使用函数头中的匹配来累积一组消耗性操作。
您必须决定的是元素的语义。现在你有元组的元组——这不是元组的目的。 {Operation, Operand}
或 {Operation, Operand1, Operand2}
形式的元组非常有意义——它们在语义上是不同的——但是 {OperationZ, {OperationX, Operand}, {OperationQ, Operand1, Operand2}}
形式的元组没有任何意义,因为元组的每个元素都是应该有不同的含义。在这里,您刚刚将一堆具有自己含义的元组嵌套到一个更大的元组中,而现在这个元组本身就很混乱了。
解决方案是使用列表,而不是元组。如果你更进一步,而不是使用 "push/pop" 作为他们自己的操作,考虑完全展开你的元组,并根据规则集以自己的方式处理列表中的每个元素 系统的基础。因此,不是将值包装在 {push, 4}
中,而是提供 4
因为隐式操作始终是推送(或弹出,具体取决于您的观点......实际上,更好的是放弃这个概念,因为堆栈已作为输入存在)。
从上面的例子中提取:
[{push,{num,4}},{push,{num,3}},{push,{num,2}},{push,plus},{push,mul}]
会变成
[4, 3, 2, add, mul]
这已经可以毫无歧义地解释了,我们不需要混淆 push
和 num
标识符:
-module(rpn).
-export([calc/1]).
calc(List) ->
[Res] = lists:foldl(fun calc/2, [], List),
Res.
calc(mul, [N1, N2 | Stack]) -> [N1 * N2 | Stack];
calc(add, [N1, N2 | Stack]) -> [N1 + N2 | Stack];
calc(X, Stack) -> [X | Stack].
希望这能说明问题,而不是造成混淆。请记住,您 可以 将所有内容都包裹在元组中并匹配元组标签和值变量,但这不是必需的。上面的代码根本没有类型检查,但是如果你向元素添加标签(但是 而不是 嵌套元组)那么你可以使用这些标签作为类型标记的形式(崩溃如果您收到错误的标签,或跳过任何意外的标签,请立即执行)——但这意味着您需要在语义上进一步后退一步:
[{num, 4}, {num, 3}, {num, 2}, {op, add}, {op, mul}]
现在稍微尝试一下,最终会使代码复杂化到某种程度,我真的宁愿只使用守卫,如果输入不好就早点崩溃。
我想删除列表中的所有元组,例如
我有这样的输入
test:stack({push, [{{mul,{plus,{num,2},{num,3}},{num,4}},[]}]}, []).
%% note: (returns wrong output because of the multiple tuples brackets)
如果我有这样的东西:
proj:stack({push, [mul,plus,{num,2},{num,3},{num,4}]}, []).
%% this would return:
%% [{push,{num,4}},{push,{num,3}},{push,{num,2}},
%% {push,plus},{push,mul}]
%% This is near to what I need.
我的代码是这样的:
stack({push, []}, StackList) -> StackList;
stack({push,[H|T]}, StackList) ->
stack({push, T}, [{push,H} | StackList]).
我想实现这样的目标:
{push, {num, 4}}, {push, {num, 3}},
{push, {num, 2}}, {add}, {mul}, {pop}, {ret}
我想过使用过滤器来实现这一点,但也许是其他原因?
这是您拥有的代码:
lists:filter(fun(E) -> E /= {} end, list1)
这不会从列表中过滤掉所有元组。这只会过滤掉等于空元组 {} 的列表元素。如果你想要一个从列表中过滤元组的函数,你应该用 not 和 is_tuple/1 BIF:
替换 lambda 表达式中的 E /= {} 谓词not is_tuple(E)
我对你最初的问题也有点困惑。你说
list1= [{1},{2},{3}] 我想要它作为 list1 = [1,2,3]
这让我觉得您想映射列表并将列表中的每个单个元素元组转换为其内容。如果这是您想要的行为,请使用 map/2 BIF 或列表理解。
[ E || {E} <- list1]
这个表达式读作,"for each single element tuple in list1, generate a new list whose elements are the contents of those tuples."
希望这对您有所帮助。享受 Erlang。
太大,无法发表评论。嗯...
这看起来很像您正在尝试构建一台堆栈计算机,在本例中可能是一个计算器。有一个 good RPN example walkthrough in LYSE 我强烈推荐你看一看。它不涉及此特定语法,但它演示了如何使用函数头中的匹配来累积一组消耗性操作。
您必须决定的是元素的语义。现在你有元组的元组——这不是元组的目的。 {Operation, Operand}
或 {Operation, Operand1, Operand2}
形式的元组非常有意义——它们在语义上是不同的——但是 {OperationZ, {OperationX, Operand}, {OperationQ, Operand1, Operand2}}
形式的元组没有任何意义,因为元组的每个元素都是应该有不同的含义。在这里,您刚刚将一堆具有自己含义的元组嵌套到一个更大的元组中,而现在这个元组本身就很混乱了。
解决方案是使用列表,而不是元组。如果你更进一步,而不是使用 "push/pop" 作为他们自己的操作,考虑完全展开你的元组,并根据规则集以自己的方式处理列表中的每个元素 系统的基础。因此,不是将值包装在 {push, 4}
中,而是提供 4
因为隐式操作始终是推送(或弹出,具体取决于您的观点......实际上,更好的是放弃这个概念,因为堆栈已作为输入存在)。
从上面的例子中提取:
[{push,{num,4}},{push,{num,3}},{push,{num,2}},{push,plus},{push,mul}]
会变成
[4, 3, 2, add, mul]
这已经可以毫无歧义地解释了,我们不需要混淆 push
和 num
标识符:
-module(rpn).
-export([calc/1]).
calc(List) ->
[Res] = lists:foldl(fun calc/2, [], List),
Res.
calc(mul, [N1, N2 | Stack]) -> [N1 * N2 | Stack];
calc(add, [N1, N2 | Stack]) -> [N1 + N2 | Stack];
calc(X, Stack) -> [X | Stack].
希望这能说明问题,而不是造成混淆。请记住,您 可以 将所有内容都包裹在元组中并匹配元组标签和值变量,但这不是必需的。上面的代码根本没有类型检查,但是如果你向元素添加标签(但是 而不是 嵌套元组)那么你可以使用这些标签作为类型标记的形式(崩溃如果您收到错误的标签,或跳过任何意外的标签,请立即执行)——但这意味着您需要在语义上进一步后退一步:
[{num, 4}, {num, 3}, {num, 2}, {op, add}, {op, mul}]
现在稍微尝试一下,最终会使代码复杂化到某种程度,我真的宁愿只使用守卫,如果输入不好就早点崩溃。