如何在Elixir中对两个列表进行XOR处理?

问题描述 投票:0回答:1

说你想 XOR 两份名单

  • list1 = [0,1,0,1]
  • list2 = [0,1,1,0]

给你一个新的列表,是 [0,0,1,1].

或者是 [1,1,0,0][1,1,1,1,1,0,1,0,1,0] 但只是 XOR 然后将第二个列表中的其余部分复制到新的列表中,这样就可以得到 [0,0,1,1,1,0,1,0,1,0].

erlang elixir
1个回答
2
投票

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

list_xor([], L) ->
    L;

list_xor(L, []) ->
    L;

list_xor([H1|T1], [H2|T2]) ->
    [H1 bxor H2 | list_xor(T1, T2)].

Elixir版本。

def list_xor([], l),
  do: l

def list_xor(l, []),
  do: l

def list_xor([h1 | t1], [h2 | t2]),
  do: [:erlang.bxor(h1, h2) | list_xor(t1, t2)]

1
投票

Oneliner,只是出于好奇。

[Stream.concat([1,1,0,0], Stream.cycle([nil])), [1,1,1,1,1,0,1,0,1,0]]
|> Enum.zip()
|> Enum.map(fn {nil, e} -> e; {e1, e2} -> :erlang.bxor(e1, e2) end)
#⇒ [0, 0, 1, 1, 1, 0, 1, 0, 1, 0]

0
投票
import Bitwise

def xor(list_1, list_2), do: do_xor(list_1, list_2, [])
defp do_xor([], [], results), do: Enum.reverse(results)
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_1 | tail_1], [element_2 | tail_2], results), do: do_xor(tail_1, tail_2, [element_1 ^^^ element_2 | results])

我们在这里做的是使用模式匹配来检查其中一个列表是否是空列表--如果是,就把当前的 element 从其他名单中的 results 列表。

如果两个列表都包含元素,则使用 Bitwise.^^^/2 来进行XOR比较。

最后,如果两个列表都是空的 ([]),反过来 results 列表并返回它。

P.S. 请注意,我们是如何在结果列表的前面进行预输入,而不是在后面进行追加(这应该像这样做 new_results = results ++ [element]),因为Elixir中的列表数据结构是以这样一种方式设置的,即向前面预搜索的速度要快得多(O(1)),而不是追加到后面(O(N)).由于我们是在前面追加到了 results 列表,结果的顺序是相反的。这就是为什么我们要做 Enum.reverse/1 在最后一步,把结果放回原来的顺序。


0
投票

如果您 use Bitwise 以获得 ^^^ 操作员,你可以简单地用一个组合来实现这一点。理解力Enum.zip/2:

use Bitwise
for {x, y} <- Enum.zip([0, 1, 0, 1], [0, 1, 1, 0]), do: x ^^^ y

输出。

[0, 0, 1, 1]

对于不同长度的列表,@choroba的递归例子(已投票)很好。下面是这个例子的一个版本,使用的是 ^^^ 运营商。

use Bitwise

defmodule Example do
  def list_xor([], l), do: l
  def list_xor(l, []), do: l
  def list_xor([h1 | t1], [h2 | t2]), do: [h1 ^^^ h2 | list_xor(t1, t2)]
end
© www.soinside.com 2019 - 2024. All rights reserved.