例如,有三个列表:
unsorted_key = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']
sorted_key = ['e', 'i', 'o', 'p', 'q', 'r', 't', 'u', 'w', 'y']
ciphertext = [
['u', 't', 'x', 'e'],
['p', 'r', 'k', 'p'],
['v', 'n', 'x', 'a'],
['n', 'h', 'e', 'x'],
['x', 'h', 'm', 's'],
['l', 'x', 'c', 'x'],
['x', 'c', 'y', 'a'],
['t', 'u', 'o', 'x'],
['e', 'r', 'm', 'e'],
['y', 'y', 'e', 'x']
]
是否可以采用sorted_key的顺序并将其排序为unsorted_key,并采用密文的顺序并以相同的方式对其进行排序?
将“ q”从sorted_key [4]移至sorted_key [0]时,应将密文[4]移至密文[0]。
我一直在考虑它,我唯一想到的方法是使用一个辅助函数来按unsorted_key的顺序动态生成并返回一个lambda函数,然后使用类似的东西:
sorted_key, ciphertext = (list(i) for i in zip(*sorted(zip(sorted_key, ciphertext), key=generate(unsorted_key))))
但是我真的不知道zip()或lambda函数是如何工作的,或者如何将自定义排序顺序变成一个,或者甚至不能返回一个用于sorted()。我真的似乎无法解决这个问题,所以任何帮助将不胜感激!
答案 0 :(得分:1)
我不确定我是否明白这一点,但是...
首先确定动作(可能相反,我不清楚):
moves = [ [i, sorted_key.index(c)] for i, c in enumerate(unsorted_key) ]
#=> [[0, 4], [1, 8], [2, 0], [3, 5], [4, 6], [5, 9], [6, 7], [7, 1], [8, 2], [9, 3]]
也许交换[i, sorted_key.index(c)]
中的元素。
将移动应用于接收者(res
):
res = [ None for _ in range(len(ciphertext))]
for a, b in moves:
res[a] = ciphertext[b]
因此输出应为:
for line in res:
print(line)
# ['x', 'h', 'm', 's']
# ['e', 'r', 'm', 'e']
# ['u', 't', 'x', 'e']
# ['l', 'x', 'c', 'x']
# ['x', 'c', 'y', 'a']
# ['y', 'y', 'e', 'x']
# ['t', 'u', 'o', 'x']
# ['p', 'r', 'k', 'p']
# ['v', 'n', 'x', 'a']
# ['n', 'h', 'e', 'x']
import timeit, functools
def custom_sort(ciphertext, sorted_key, unsorted_key):
return [ ciphertext[b] for _, b in [ [i, sorted_key.index(c)] for i, c in enumerate(unsorted_key) ] ]
custom_sort = timeit.Timer(functools.partial(custom_sort, ciphertext, sorted_key, unsorted_key))
print(custom_sort.timeit(20000))
答案 1 :(得分:1)
在线性时间内解决此问题的有效方法是创建一个将键映射到sorted_key
的索引的字典,然后创建一个将unsorted_key
的索引映射到{{ 1}}基于相同的键,因此您可以遍历sorted_key
长度范围的索引以按映射顺序生成列表:
ciphertext
这将输出:
order = dict(map(reversed, enumerate(sorted_key)))
mapping = {i: order[k] for i, k in enumerate(unsorted_key)}
print([ciphertext[mapping[i]] for i in range(len(ciphertext))])
答案 2 :(得分:1)
带有自定义键的内置sorted
可以为您做到:
sorted(ciphertext, key=lambda x: unsorted_key.index(sorted_key[ciphertext.index(x)]))
输出:
[['x', 'h', 'm', 's'],
['e', 'r', 'm', 'e'],
['u', 't', 'x', 'e'],
['l', 'x', 'c', 'x'],
['x', 'c', 'y', 'a'],
['y', 'y', 'e', 'x'],
['t', 'u', 'o', 'x'],
['p', 'r', 'k', 'p'],
['v', 'n', 'x', 'a'],
['n', 'h', 'e', 'x']]
lambda基本上可以归结为:
sorted_key
中找到当前索引的值sorted_key
中找到unsorted_key
值的索引我不清楚的一件事是,如果最终结果与sorted_key
相同,为什么需要对unsorted_key
进行“排序”?在这种情况下,sorted_key = unsorted_key[:]
就足够简单了。但是,如果您真的也需要对sorted_key
进行排序,则可以执行此操作(实际上会使lambda
更加简单):
ciphertext, sorted_key = map(list, zip(*sorted(zip(ciphertext, sorted_key), key=lambda x: unsorted_key.index(x[1]))))
ciphertext
[['x', 'h', 'm', 's'],
['e', 'r', 'm', 'e'],
['u', 't', 'x', 'e'],
['l', 'x', 'c', 'x'],
['x', 'c', 'y', 'a'],
['y', 'y', 'e', 'x'],
['t', 'u', 'o', 'x'],
['p', 'r', 'k', 'p'],
['v', 'n', 'x', 'a'],
['n', 'h', 'e', 'x']]
sorted_key
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p']
答案 3 :(得分:0)
我不确定我是否正确理解了您的问题,但是如果您尝试对未排序的密钥进行排序,并确保对密文进行了相应的排序,那么这应该可以满足您的要求:
pairs = zip(unsorted_key, ciphertext)
sorted_key = []
sorted_ciphertexts = []
for t in sorted(pairs):
sorted_key.append(t[0])
sorted_ciphertexts.append(t[1])
我敢肯定,可能有一种更优雅的方法,但这将确保密钥和密文位于相同的索引上。