字典理解不符合预期

时间:2015-06-21 12:15:32

标签: python dictionary

def tf(tokens):
    """ Compute TF
    Args:
        tokens (list of str): input list of tokens from tokenize
    Returns:
        dictionary: a dictionary of tokens to its TF values
    """
    li = {}
    total = len(tokens)
    li = {token: 1 if not token in li else li[token] + 1 for token in tokens }
    return {token: li[token]/ float(total) for token in li}

基本上,我想要一个字典,其中令牌是键,值是令牌列表中该令牌的频率。

我希望我的理解能够检查令牌是否已经在li中。如果它只是将其值增加1,如果不是,则创建它并将其值设置为1.

出于某种原因,无论在令牌列表中出现多少次,每个键的最终值都为(1)。

你能帮我看看为什么会这样吗?

我可以通过循环解决它,但我想掌握字典理解。

非常感谢你!

4 个答案:

答案 0 :(得分:2)

列表/字典理解之类的理解表达式是构建器表达式,并且在完全计算表达式之前不会构造对象。在生成的字典的引用之后,将符号名称赋值给它。

在您的特定示例中,您指的是符号li,它引用了对象空字典。因此,在评估表达式时,li继续引用一个空字典,这意味着,字典理解可以等效地写为

li = {token: 1 if not token in {} else l{}[token] + 1 for token in tokens }

或简化为空字典的成员资格测试始终为假

li = {token: 1  for token in tokens }

您需要的是已有的库实用程序或基于状态的解决方案。

幸运的是,标准库collections提供了一个名为counter的函数,该函数是为此目的而编写和设计的。

这只是你的功能

def tf(tokens):
    from collections import Counter
    """ Compute TF
    Args:
        tokens (list of str): input list of tokens from tokenize
    Returns:
        dictionary: a dictionary of tokens to its TF values
    """
    return Counter(tokens)

基于状态的解决方案只需要每个唯一事件的外部计数器

def tf(tokens):
    from collections import defaultdict
    """ Compute TF
    Args:
        tokens (list of str): input list of tokens from tokenize
    Returns:
        dictionary: a dictionary of tokens to its TF values
    """
    counter = defaultdict(int)
    for token in tokens:
          counter[token] += 1
    return counter

或者如果您不打算使用defaultdict

def tf(tokens):
    from collections import defaultdict
    """ Compute TF
    Args:
        tokens (list of str): input list of tokens from tokenize
    Returns:
        dictionary: a dictionary of tokens to its TF values
    """
    counter = {}
    for token in tokens:
          counter[token] = counter.get(token, 0) + 1
    return counter

答案 1 :(得分:1)

字典理解首先执行,生成 new 字典对象。只有当该表达式完成时,才li绑定到该新词典。

换句话说,这就是幕后发生的事情,没有_result在循环中可供参考:

li = {}
_result = {}
for token in tokens:
    _result[token] = 1 if not token in li else li[token] + 1
li = _result

由于li在整个循环期间为空,token in li始终为False。字典理解本身工作得很好。

如果您想计算值,可以只是使它成为显式循环:

li = {}
for token in tokens:
    li[token] = 1 if not token in li else li[token] + 1

但你最好使用collections.Counter() object,它封装了相同的程序并在顶部添加了其他功能:

from collections import Counter

def tf(tokens):
    li = Counter(tokens)
    total = float(len(tokens))
    return {token: li[token] / total for token in li}

答案 2 :(得分:0)

使用Counter词典:

from collections import Counter
li = Counter(tokens)

使用普通字典需要使用for循环和dict.setdefault

li = {}

for t in tokens:
    li.setdefault(t,0) # if key not yet added create key/value pairing
    li[t] += 1 # increment count for the key

你不能增加dict理解中的计数,因为你总是会得到1的计数,你需要一个Counter dict或一个显式循环来处理重复键,因为li指的是空字典直到理解完成。

if not token in li始终为True,因此您始终将值设置为1

所以在你的函数中使用Couner dict并遍历项目:

def tf(tokens):
    """ Compute TF
    Args:
        tokens (list of str): input list of tokens from tokenize
    Returns:
        dictionary: a dictionary of tokens to its TF values
    """
    total = float(len(tokens))
    li = Counter(tokens)
    return {token: v / float(total) for token,v in li.iteritems()}

答案 3 :(得分:0)

def tf(tokens):
    mydic = {}
    for key in tokens:
        if key not in mydic:
            mydic[key] = 1
        else:
            mydic[key] = mydic[key] + 1
    d2 = dict((k, float(v)/len(tokens)) for k,v in mydic.items())            
    return d2