2

I realise that using a functional paradigm everywhere does not always result in very readable code -- the code segment below is something I'm doing just as an exercise. What I'm trying to do is as follows :-

Given a list of strings(L) and a string(S) I need to find L[i]^S. If S exists in L, don't xor the strings together. L[i]^S would mean xoring the bytes in the same position with each other.

This is how I proceeded to solve the problem. I tried to break it down to its simplest form - i.e. xoring of two characters. If one of the inputs wouldn't be a character, I return a "".(I couldn't think of a better way to do this).

xor_char   = lambda x, y: (chr(ord(x) ^ ord(y)) if x and y else "")
assert xor_char(None, "a") == ""
assert xor_char("a", " ")  == "A"

Next, I try to write some code to xor the strings together.

from operator import add
xor_string = lambda string_one, string_two: reduce(add, (map(xor_char, string_one, string_two) if string_one != string_two else ""))
assert xor_string("asdf", "asdfg") == "\x00\x00\x00\x00"
assert xor_string("asdf", "    ")  == "ASDF"

Then, finally I try to perform this on a list of strings and a string.

xor_list_string = lambda l, s: map(xor_string, l, [s]*len(l))
print xor_list_string(a_list, a_string)

I get an error as follows on running the above line :-

Traceback (most recent call last):
  File "2.py", line 26, in <module>
    main()
  File "2.py", line 23, in main
    analyze(all_lines, all_lines[-1])
  File "2.py", line 18, in analyze
    print xor_list_string(a_list, a_string)
  File "2.py", line 17, in <lambda>
    xor_list_string = lambda l, s: map(xor_string, l, [s]*len(l))
  File "2.py", line 11, in <lambda>
    xor_string = lambda string_one, string_two: reduce(add, (map(xor_char, string_one, string_two) if string_one != string_two else ""))
TypeError: reduce() of empty sequence with no initial value
  • What am I doing wrong?

  • Is there anything wrong with how I'm trying to solve the problem using functional programming?

  • Any obvious improvements you can think of?(the improvements would have to adhere to the functional paradigm too -- I'm doing this as a thought exercise, not in any project).
4

3 回答 3

4

我会使用 xor 2 个字符串zip

l = [ord(s1) ^ ord(s2) for s1,s2 in zip(str1,str2)]
于 2013-11-10T16:44:59.520 回答
1

好的,据我了解,如果不相等,您需要将字符串l列表中的每个字符串L与字符串异或。b您可以为此使用列表推导:

In [1]: L = ['a', 'b', 'c', 'd', 'e', 'f']
In [2]: S = 'c'
In [3]: [ chr( ord(l) ^ ord(S)) if l is not S else S for l in L]
Out[3]: ['\x02', '\x01', 'c', '\x07', '\x06', '\x05']

我们for l in L用来遍历 L 列表,然后我们正在检查 l 元素是否等于 S ( if l is not S else S),如果这有效,我们将进行 xor-ing 部分。

好的,我玩过你的代码。减少内部发电机的问题。如果字符串相同,它会为您提供空列表。你可以通过if使用 lambda 而不是 reduce 来解决这个问题。像这样:

a_list = [ 'as', 'qwe', 'vcs', 'ase', 'wsc', 'ase', 'sa' ]
a_string = 'sa'

xor_char   = lambda x, y: (chr(ord(x) ^ ord(y)) if x and y else "")
assert xor_char(None, "a") == ""
assert xor_char("a", " ")  == "A"

from operator import add
xor_string = lambda string_one, string_two: reduce(add, map(xor_char, string_one, string_two)) if string_one != string_two else ''
assert xor_string("asdf", "asdfg") == "\x00\x00\x00\x00"
assert xor_string("asdf", "    ")  == "ASDF"

xor_list_string = lambda l, s: map(xor_string, l, [s]*len(l))
print xor_list_string(a_list, a_string)

输出:

['\x12\x12', '\x02\x16', '\x05\x02', '\x12\x12', '\x04\x12', '\x12\x12', '']
于 2013-11-10T17:07:12.403 回答
1

reduce将初始化程序传递给这样总是好的

reduce(add, (map(xor_char, string_one, string_two) if string_one != string_two else ""), "")
于 2013-11-10T16:40:56.530 回答