Python:通过避免重复相同的比较来加速我的循环

时间:2016-11-02 09:41:29

标签: python list loops

我正在研究一种检查英语单词之间相似性的算法。

定义了一个名为“相似性”的函数后,我会检查整个单词列表以检查相似的单词,如果两个单词之间的相似度非常高(= 1),算法会将这两个单词中的一个更改为另一个。

以下是逻辑:

PropertyChangedCallback

假设word1和word4之间存在非常高的相似性。

结果:

$path = getcwd() . '/uploads/data.csv' ;
    $sql = "SELECT 'Name', 'Email', 'Type of inquiry' , 'Message'
            UNION ALL
            SELECT `engine4_mytable_contacts`.name ,
            `engine4_mytable_contacts`.email, 
            `engine4_mytable_contacts`.topic,
            `engine4_mytable_contacts`.feed_back
            FROM engine4_mytable_contacts WHERE contact_date >= '$prevDate' into outfile '$path' FIELDS TERMINATED BY ','   ENCLOSED BY '\"'  LINES TERMINATED BY '\n\r'";

$result = $connection->prepare($sql);
$result->execute();
通常,我只需要循环它,所采取的步骤将是:

  1. 将word1取出,与word1,word2,word3,word4
  2. 相比较
  3. 将word2取出,与word1,word2,word3,word4
  4. 相比较
  5. 将word3取出,与word1,word2,word3,word4
  6. 相比较
  7. 将word4取出,与word1,word2,word3,word4
  8. 相比较

    然而,有一些无用且重复的动作。例如,我不必多次比较 word1 word2

    问题是我必须经历100万字,可能需要很多天才能运行。

    有什么建议吗?

    以下是我目前使用的代码:

    list_of_word = [word1, word2, word3, word4]
    

3 个答案:

答案 0 :(得分:1)

只需使用嵌套循环,其中第二个索引从第一个索引开始:

for i in xrange(len(results)):
    for j in xrange(i+1, len(results)):
        # compare element i and j

当然,这种优化(将计算除以2)仅起作用,因为您的相似性度量是对称的(类似于b == b类似于a)。此外,这不会改变计算复杂性,它仍然是O(n ^ 2)(更确切地说:O(n(n-1)/ 2))。

另一种但更复杂的计算相似性度量的计算效率更高的方法是使用二项式扩展(稍后我将在此处添加更多内容)。

此外,你应该避免while循环,通常它们可以被for循环替换。这是更可靠的(没有无限循环),可以通过解释器更加优化。

答案 1 :(得分:1)

假设您的所有单词列表都不重复(表示您已将它们放入集中)

恕我直言,你可以在相似性中应用集理论数学。

如果A类似于B,而X也类似于B,则意味着A也类似于X.

所以你有一套单词 [“汽车”,“公共汽车”,“猫”,“狗”,“钢笔”,“鸭子”,“摩托车”]

如同“机动车”的相似属性,如果“汽车”类似于“公共汽车”,“汽车”类似于“摩托车”。因此“公共汽车”也类似于“摩托车”。所以你可以看到,你< strong>不需要比较已找到的所有相似单词。所以在“汽车”相似性比较完成后,它已经被带走了 [“汽车”,“公共汽车”,“摩托车”]。 “公共汽车”,“摩托车”不需要再次用于比较。

你只剩下[“猫”,“狗”,“笔”,“鸭子”等)。

接下来需要做的是保留一个类似位置的索引。也许第二次检查距离得分。

(更新) 重要说明:在自然语言中,同一动词和名词可以有多种含义,例如:鸡肉可能意味着懦夫。例如。你可能会错过组合词,谚语等。例如。 鸡出来与鸡出去无关; 体外是一个动词,你无法将它们分开。 以上方法非常积极。但是你需要从某个地方开始,然后逐步添加更多功能来完善它们。

答案 2 :(得分:0)

目前,您会检查列表中的每个单词与列表中的每个其他单词。这正是n 2

你可以通过检查每个单词后面的每个单词来减少这一点。这是1 + 2 + ... +(n-1)+ n = n(n-1)/ 2。这会对您的支票进行重复数据删除。虽然你的支票需要是对称的。

from nltk.corpus import wordnet as wn
from itertools import product

def similarity(wordx,wordy):
    sem1, sem2= wn.synsets(wordx), wn.synsets(wordy)
    maxscore = 0
    for i,j in list(product(*[sem1,sem2])):
        score = i.path_similarity(j) # Wu-Palmer Similarity
        maxscore = score if maxscore < score else maxscore
    return maxscore

def group_high_similarity(target_list,tc):
    result = target_list[:]
    for x in xrange(0, len(target_ist)):
        for y in xrange(x + 1, len(target_list)):
            wordx, wordy = target_list[x], target_list[y]
            value = similarity(wordx,wordy)
            if  value >= tc:
                result[x] = wordx
                if wordy != wordx :print wordy+"---> "+ wordx
    return result

它可能仍需要很长时间才能运行,因为它现在只有一半大小。