2015-06-21 41 views
1
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),无论它出现多少次在令牌列表中。

你能帮我看看为什么会发生这种情况吗?

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

非常感谢!

回答

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 

你不能在一个字典理解递增计数,你将永远最后计数为1,您需要一个Counter字典或一个显式循环来处理重复键,因为li指的是空字典,直到理解完成为止。

if not token in li始终是真实的,所以你总是那么在你的函数使用Couner字典和迭代值设置为1

在项目:

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()} 
1

字典理解执行第一,产生一个新的字典对象。只有当表达式完成时,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} 
+0

'itertools.Counter()object'?我认为你的意思是'collections.Counter()' – Abhijit

+0

@Ahhijit:我当然了。呃,甚至不知道为什么Chrome自动完成URL,我以前一定犯过错误。关闭网站搜索引擎! –

+0

@Abhijit:bingo,[用变量名称键添加项到词典python](https://stackoverflow.com/a/12732835)已更正。 –

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 
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