对嵌套列表中的某个元素进行排序并去重

编程语言 2026-07-09

我在用Python实现一个爬山法来解密密码。爬山法把ngram计数、解密后的消息,以及字母表作为一个列表添加到当前输出列表中。同一个消息在不同字母表下可能被生成多次,我想先按消息排序以去除重复项,然后再按ngram计数排序,以便让输出按数值顺序排列。也就是说,如果我有:

output = [[10, 'HELLO', 'ABCD'], [10, 'HELLO', 'ABDC'], [18, 'HLELO', 'BCDA']]

[为清晰起见的编辑] 好的,爬山法正在处理一个简单的替换消息(a=h、b=x、c=m等等)。对于短明文,并非字母表中的所有字母都会出现在密文中。我所做的是识别密文中的唯一字母,将它们放在列表的前面,然后再用其余缺失字母对列表进行填充。爬山法在第二个列表中随机分配明文字母,并尝试用这两个字母表来解密消息。如果密文字母表因为消息较短而只使用18个字母,那么该列表中的前18个字母才是相关的,因此类似于

'JOHNABCDEFGIKLMPQRZYXSTUVW' 和 'JOHNABCDEFGIKLMPQRWVUSTZXY'

将产生相同的“明文”输出,且ngram计数也相同。我按ngram计数排序,以得到最接近普通英语频率分布的前200条结果,而且我只需要每条消息的一份拷贝来判断它是否是正确的解密。我想丢弃重复项。

由于未使用的字母在简单替换步骤中是必需的,我需要把它们保留在密文字母表列表中,但未使用的字母对密钥恢复没有贡献(我只需要上面的例子中的 "JOHN" 就能知道真实密钥是什么)。这意味着在唯一排序之后,保留哪一个字母表并不重要,因为每个字母表只需要前18个字母就够了。而且如示例中,前18个字母会产生两个相同的解密,因此ngram计数(也就是结果中诸如 'ed'、'er'、'ing' 这类常见字母组合出现的次数)将是相同的。

解决方案

如果你真的不在意所谓的“字母表”(换言之,子列表的第三个元素),你可以按如下操作:

from itertools import groupby

output = [[10, 'HELLO', 'ABCD'], [10, 'HELLO', 'ABDC'], [18, 'HLELO', 'BCDA']]
res = [next(g) for k, g in 
       groupby(sorted(output, key=lambda x: x[:2]),
               key = lambda x: x[:2])]

结果:

[[10, 'HELLO', 'ABCD'], [18, 'HLELO', 'BCDA']]
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章