Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Elixir中对两个列表进行异或_Elixir - Fatal编程技术网

如何在Elixir中对两个列表进行异或

如何在Elixir中对两个列表进行异或,elixir,Elixir,假设您想对两个列表进行异或运算 列表1=[0,1,0,1] 列表2=[0,1,1,0] 为您提供一个新列表,即[0,0,1,1] 或者可能是[1,1,0,0]和[1,1,1,1,1,0,1,0],但只对前4个进行异或运算,然后将第二个列表中的其余部分复制到新列表中,得到[0,0,1,1,1,0,1,0,0,1,0]。在Erlang中,可以使用递归定义 列表\u xor[],L-> L 列表\u xorL,[]-> L 列表异或[H1 | T1],[H2 | T2]-> [H1 bxor H2 |

假设您想对两个列表进行异或运算

列表1=[0,1,0,1] 列表2=[0,1,1,0] 为您提供一个新列表,即[0,0,1,1]


或者可能是[1,1,0,0]和[1,1,1,1,1,0,1,0],但只对前4个进行异或运算,然后将第二个列表中的其余部分复制到新列表中,得到[0,0,1,1,1,0,1,0,0,1,0]。

在Erlang中,可以使用递归定义

列表\u xor[],L-> L 列表\u xorL,[]-> L 列表异或[H1 | T1],[H2 | T2]-> [H1 bxor H2 |列表_xorT1,T2]。 长生不老药版本:

定义列表\u xor[],l, do:我 def列表\u xorl,[], do:我 定义列表异或[h1 | t1],[h2 | t2], do:[:erlang.bxorh1,h2 | list_xort1,t2]
在Erlang中,可以使用递归来定义

列表\u xor[],L-> L 列表\u xorL,[]-> L 列表异或[H1 | T1],[H2 | T2]-> [H1 bxor H2 |列表_xorT1,T2]。 长生不老药版本:

定义列表\u xor[],l, do:我 def列表\u xorl,[], do:我 定义列表异或[h1 | t1],[h2 | t2], do:[:erlang.bxorh1,h2 | list_xort1,t2] 按位导入 def xorlist_1,list_2,do:do xorlist_1,list_2,[] defp do_xor[],[],结果,do:Enum.reverseresults defp do_xor[element_1 | tail_1],],results,do:do_xor tail_1,[],[element_1 | results] defp do_xor[],[element_2 | tail_2],results,do:do_xor[],tail_2,[element_2 | results] defp do|xor[element|u 1 | tail|u 1],[element|u 2 | tail|u 2],results,do:do|xor tail|u 1,tail|u 2,[element|u 1^^ element|u 2 | results] 我们在这里所做的是使用模式匹配来检查其中一个列表是否为空列表-如果是空列表,只需将另一个列表中的当前元素头附加到结果列表中即可

如果两个列表都包含元素,请使用按位。^^/2进行异或比较

最后,如果两个列表都为空[],请反转结果列表并返回它

注意,我们是如何在结果列表的前面进行预处理的,而不是在后面追加,这将像new_results=results++[element]一样进行,因为Elixir中的列表数据结构的设置方式是,在前面进行预处理要比在后面追加快得多。 由于我们将结果添加到结果列表的前面,因此结果的顺序是相反的。这就是为什么我们在最后一步中执行Enum.reverse/1,以将结果恢复到原始顺序。

按位导入 def xorlist_1,list_2,do:do xorlist_1,list_2,[] defp do_xor[],[],结果,do:Enum.reverseresults defp do_xor[element_1 | tail_1],],results,do:do_xor tail_1,[],[element_1 | results] defp do_xor[],[element_2 | tail_2],results,do:do_xor[],tail_2,[element_2 | results] defp do|xor[element|u 1 | tail|u 1],[element|u 2 | tail|u 2],results,do:do|xor tail|u 1,tail|u 2,[element|u 1^^ element|u 2 | results] 我们在这里所做的是使用模式匹配来检查其中一个列表是否为空列表-如果是空列表,只需将另一个列表中的当前元素头附加到结果列表中即可

如果两个列表都包含元素,请使用按位。^^/2进行异或比较

最后,如果两个列表都为空[],请反转结果列表并返回它

注意,我们是如何在结果列表的前面进行预处理的,而不是在后面追加,这将像new_results=results++[element]一样进行,因为Elixir中的列表数据结构的设置方式是,在前面进行预处理要比在后面追加快得多。
由于我们将结果添加到结果列表的前面,因此结果的顺序是相反的。这就是为什么我们在最后一步中执行Enum.reverse/1,以将结果恢复到原始顺序。

Oneliner,只是出于好奇

[Stream.concat[1,1,0,0],Stream.cycle[nil],[1,1,1,1,0,1,0,1,0]] |>Enum.zip |>Enum.mapfn{nil,e}->e;{e1,e2}->:erlang.bxore1,e2结束 ⇒ [0, 0, 1, 1, 1, 0, 1, 0, 1, 0]
一行,只是出于好奇

[Stream.concat[1,1,0,0],Stream.cycle[nil],[1,1,1,1,0,1,0,1,0]] |>Enum.zip |>Enum.mapfn{nil,e}->e;{e1,e2}->:erlang.bxore1,e2结束 ⇒ [0, 0, 1, 1, 1, 0, 1, 0, 1, 0] 如果使用按位获取运算符,只需将and组合起来即可:

按位使用 对于{x,y}而言,如果使用按位获取运算符,只需将a和组合起来即可:

按位使用
对于{x,y},[1,1,1,1,0,1,0]和[1,1,0,0]会发生什么情况?[0,0,1,1,1,1,1,0,1,0]会出现什么情况?OK,更新了解决方案。[1,1,1,1,1,0,1,0]和[1,1,0,0]会发生什么情况?[0,0,1,1,1,1,1,0]会出现什么情况?OK,更新了解决方案。尾部递归的使用很好。我做了一个快速基准测试,其性能似乎与非尾部递归版本大致相同,至少对于我测试的小列表是如此。非尾部递归版本也更简单,因为它在调用堆栈中构建结果,不需要results变量和其他函数子句,所以我可能会这么说。非尾部递归版本@choroba的答案的问题不是缺乏性能,而是它会在足够大的列表中造成内存泄漏。每一次
调用一个函数,ErlangVM添加一个堆栈帧,并分配一些内存。现在想象一个包含很多元素的列表。如果没有尾部递归,它将继续分配越来越多的内存,应用程序将崩溃。因为Erlang VM实现了尾部调用优化,所以它基本上在递归调用函数时重复使用相同的帧,而不是分配新内存!我以前没读过这个,谢谢!我的观点仍然站在这里——我不是在谈论函数执行的速度,而是关于内存分配。如果我们有一个预先确定的列表大小,并且我们知道我们有足够的内存,那么两者都可以,但是如果输入可以是一个大小为N的列表,而没有尾部递归,那么我们就处于危险之中。不管您是将列表存储在累加器中还是存储在调用堆栈中,它可能会使用相同的内存量。但是添加一个列表反转会使尾部递归版本更糟糕。在上面的链接中讨论了这一点。尾部递归的良好使用。我做了一个快速基准测试,其性能似乎与非尾部递归版本大致相同,至少对于我测试的小列表是如此。非尾部递归版本也更简单,因为它在调用堆栈中构建结果,不需要results变量和其他函数子句,所以我可能会这么说。非尾部递归版本@choroba的答案的问题不是缺乏性能,而是它会在足够大的列表中造成内存泄漏。每次调用函数时,Erlang VM都会添加一个堆栈帧并分配一些内存。现在想象一个包含很多元素的列表。如果没有尾部递归,它将继续分配越来越多的内存,应用程序将崩溃。因为Erlang VM实现了尾部调用优化,所以它基本上在递归调用函数时重复使用相同的帧,而不是分配新内存!我以前没读过这个,谢谢!我的观点仍然站在这里——我不是在谈论函数执行的速度,而是关于内存分配。如果我们有一个预先确定的列表大小,并且我们知道我们有足够的内存,那么两者都可以,但是如果输入可以是一个大小为N的列表,而没有尾部递归,那么我们就处于危险之中。不管您是将列表存储在累加器中还是存储在调用堆栈中,它可能会使用相同的内存量。但是添加一个列表反转会使尾部递归版本更糟糕。这将在上面的链接中讨论。