如何在Python中有效地比较大型列表?

如何在Python中有效地比较大型列表?,python,algorithm,list,processing-efficiency,Python,Algorithm,List,Processing Efficiency,我试图找到9个字母的单词,当你平均分成3个部分,然后混在一起,你会得到另一个9个字母的单词 for i in nineWordList: for j in nineWordList: if (i[3:5] + i[0:2] + i[6:8]) == j: correctWords.append(i) elif (i[3:5] + i[6:8] + i[0:2]) == j: correctWords.appe

我试图找到9个字母的单词,当你平均分成3个部分,然后混在一起,你会得到另一个9个字母的单词

for i in nineWordList:
    for j in nineWordList:
        if (i[3:5] + i[0:2] + i[6:8]) == j:
            correctWords.append(i)
        elif (i[3:5] + i[6:8] + i[0:2]) == j:
            correctWords.append(i)
        elif (i[0:2] + i[6:8] + i[3:5]) == j:
            correctWords.append(i)
        elif (i[6:8] + i[0:2] + i[3:5]) == j:
            correctWords.append(i)
        elif (i[6:8] + i[3:5] + i[0:2]) == j:
            correctWords.append(i)
我就是这样做的。唯一的问题是nineWordList的长度是68000个元素,这需要很多时间。如何改进此功能,使其更高效?

使用a避免在列表中循环两个级别:

nineWordSet = set(nineWordList)
for i in nineWordSet:
    if i[3:5] + i[0:2] + i[6:8] in nineWordSet:
        correctWords.append(i)
    elif i[3:5] + i[6:8] + i[0:2] in nineWordSet:
        correctWords.append(i)
    elif i[0:2] + i[6:8] + i[3:5] in nineWordSet:
        correctWords.append(i)
    elif i[6:8] + i[0:2] + i[3:5] in nineWordSet:
        correctWords.append(i)
    elif i[6:8] + i[3:5] + i[0:2] in nineWordSet:
        correctWords.append(i)
这仍然需要遍历所有68000个条目(您显然无法避免),但在第一次遍历时,它会将列表转换为一个集合,因此可以在固定时间内使用中的
进行成员资格测试。这将为您提供线性时间复杂度,而不是嵌套循环所具有的二次时间复杂度。当然,额外的设置需要更多的内存,但这不应该是一个问题


顺便说一句,我相信你的切片是关闭的
i[0:2]
将不会生成3个字母的单词(当您要平均拆分9个字母的单词时):

切片中的第二个索引始终为非包含索引,因此需要将其增加一个:

>>> x[0:3], x[3:6], x[6:9]
('abc', 'def', 'ghi')
您还可以使用来生成那些可能的跳转单词,从而稍微缩短条件。这样,您的支票可能会更美观:

import itertools
nineWordSet = set(nineWordList)

for word in nineWordSet:
    for perm in itertools.permutations((word[0:3], word[3:6], word[6:9])):
        # skip the original permutation
        if perm == word:
            continue

        elif perm in nineWordSet:
            correctWords.append(word)

            # stop checking for more permutations
            break

将所有有效的单词放在Python集中,然后在集合中循环,按照您描述的方式重新排列单词。对于每次重新排列,检查是否在集合中

由于Python的集合是在
O(1)
(常数)时间内进行查找。对于每个单词的固定数量的重新排列,您的算法在
O(n)
时间内工作,这比您现在使用的
O(n^2)
算法要好得多

修订后的代码如下所示:

nineWordSet = set(nineWordList)
for i in nineWordSet:
  if i[3:5] + i[0:2] + i[6:8] in nineWordSet:
    correctWords.append(i)
  elif i[3:5] + i[6:8] + i[0:2] in nineWordSet:
    correctWords.append(i)
  elif i[0:2] + i[6:8] + i[3:5] in nineWordSet:
    correctWords.append(i)
  elif i[6:8] + i[0:2] + i[3:5] in nineWordSet:
    correctWords.append(i)
  elif i[6:8] + i[3:5] + i[0:2] in nineWordSet:
    correctWords.append(i)

您以前的代码很慢,因为对于每个单词,您必须查看所有其他单词(从技术上讲,平均为一半)。这大约是2312000000字,你必须看;这就是
O(n^2)
的意思。在每个单词的新代码中,您只需查看一个定义良好的位置,因此您只需查看68000个单词。这就是的好处,它通常可以在数据集上为您提供
O(n)
性能。

如果
correctWords
成为一个集合,您可以将
for j
循环替换为
If something in correctWords
,并且速度足够快,O(日志条目)。谢谢!工作得很好!顺便说一句,尽管你在for循环中写的是“w”而不是“word”,但请注意,这两种算法可能产生不同的结果。第二种方法收集原始列表中出现的所有排列,但原始单词除外(有争议)。而第一个算法(if…elif…elif…)只记录第一个匹配-所有进一步的排列都被错误地跳过。@user1016274否,在我的第二个代码示例中,添加到
correctWords
的是原始
word
,而不是排列
perm
。一旦找到任何排列匹配,该单词的剩余排列将不再被查看(这就是
中断
所做的,本质上移动到下一个
单词
)。
nineWordSet = set(nineWordList)
for i in nineWordSet:
  if i[3:5] + i[0:2] + i[6:8] in nineWordSet:
    correctWords.append(i)
  elif i[3:5] + i[6:8] + i[0:2] in nineWordSet:
    correctWords.append(i)
  elif i[0:2] + i[6:8] + i[3:5] in nineWordSet:
    correctWords.append(i)
  elif i[6:8] + i[0:2] + i[3:5] in nineWordSet:
    correctWords.append(i)
  elif i[6:8] + i[3:5] + i[0:2] in nineWordSet:
    correctWords.append(i)