【问题标题】:Perform set operation difference on a list of tuples对元组列表执行设置操作差异
【发布时间】:2012-03-29 09:36:56
【问题描述】:

我试图找出两个容器之间的区别,但容器的结构很奇怪,所以我不知道对其进行区别的最佳方法是什么。一种容器类型和结构我不能改变但我可以改变其他人(可变分隔符)。

delims = ['on','with','to','and','in','the','from','or']
words = collections.Counter(s.split()).most_common()
# words results in [("the",2), ("a",9), ("diplomacy", 1)]

#I want to perform a 'difference' operation on words to remove all the delims words
descriptive_words = set(words) - set(delims)

# because of the unqiue structure of words(list of tuples) its hard to perform a difference
# on it. What would be the best way to perform a difference? Maybe...

delims = [('on',0),('with',0),('to',0),('and',0),('in',0),('the',0),('from',0),('or',0)]
words = collections.Counter(s.split()).most_common()
descriptive_words = set(words) - set(delims)

# Or maybe
words = collections.Counter(s.split()).most_common()
n_words = []
for w in words:
   n_words.append(w[0])
delims = ['on','with','to','and','in','the','from','or']
descriptive_words = set(n_words) - set(delims)

【问题讨论】:

    标签: python set set-difference


    【解决方案1】:

    删除所有分隔符来修改words怎么样?

    words = collections.Counter(s.split())
    for delim in delims:
        del words[delim]
    

    【讨论】:

    • 看起来很有效率我想我会用它但是 words 是一个元组列表我怎么能说“words[delim]”?
    • @JakeM - 将其直接应用于 Counter 对象。
    • 啊,我在想单词是 Counter 对象
    【解决方案2】:

    我会怎么做:

    delims = set(['on','with','to','and','in','the','from','or'])
    # ...
    descriptive_words = filter(lamdba x: x[0] not in delims, words)
    

    使用过滤器方法。一个可行的替代方案是:

    delims = set(['on','with','to','and','in','the','from','or'])
    # ...
    decsriptive_words = [ (word, count) for word,count in words if word not in delims ]
    

    确保delims 在允许O(1) lookup 的集合中。

    【讨论】:

    • 第一种方法使用 'in',这是否意味着在每次比较时我们都在迭代整个 delim?
    • 如果它们是集合或字典则不会。 O(1) 查找,the docs say.
    【解决方案3】:

    最简单的答案是这样做:

    import collections
    
    s = "the a a a a the a a a a a diplomacy"
    delims = {'on','with','to','and','in','the','from','or'}
    // For older versions of python without set literals:
    // delims = set(['on','with','to','and','in','the','from','or'])
    words = collections.Counter(s.split())
    
    not_delims = {key: value for (key, value) in words.items() if key not in delims}
    // For older versions of python without dict comprehensions:
    // not_delims = dict(((key, value) for (key, value) in words.items() if key not in delims))
    

    这给了我们:

    {'a': 9, 'diplomacy': 1}
    

    另一种选择是先发制人:

    import collections
    
    s = "the a a a a the a a a a a diplomacy"
    delims = {'on','with','to','and','in','the','from','or'}
    counted_words = collections.Counter((word for word in s.split() if word not in delims))
    

    在这里,您在将单词列表提供给计数器之前对其应用过滤,这会产生相同的结果。

    【讨论】:

      【解决方案4】:

      如果您仍然在迭代它,为什么还要麻烦将它们转换为集合?

      dwords = [delim[0] for delim in delims]
      words  = [word for word in words if word[0] not in dwords]
      

      【讨论】:

      • @Rob Young 是的,我试图避免对它们进行迭代以提高效率。我认为任何不迭代的解决方案都是最好的
      • 坏主意。这将是 O(n^2),不是吗?
      【解决方案5】:

      为了提高性能,您可以使用 lambda 函数

      filter(lambda word: word[0] not in delim, words)
      

      【讨论】:

      • filter+lambda 的可读性不如列表推导,而列表推导可以often be faster
      • 其次,这仍然在做 O(n^2),因为 delims 是一个列表。
      猜你喜欢
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 2011-09-16
      • 2018-12-09
      • 2011-12-11
      • 2023-01-12
      • 1970-01-01
      • 2013-10-23
      相关资源
      最近更新 更多