在对列表中查找对项的频率

Mor*_*a R 3 python dictionary list python-3.x

假设我有一个很长的这种类型列表:

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b'], ... ]
Run Code Online (Sandbox Code Playgroud)

鉴于第一个元素,我想构建一个显示第二个元素计数的字典.例如,在上面的特定示例中,我希望有这样的事情:

{'a': {'b':2, 'd':1},
 'w': {'a':1}
}
Run Code Online (Sandbox Code Playgroud)

这是我试图解决它的方法失败了.我构建了一个独特的第一个元素列表.我们打电话words然后:

dic = {}

for word in words:
  inner_dic = {}
  for pair in text:
    if pair[0] == word:
      num = text.count(pair)
      inner_dic[pair[1]] = num
  dic[pair[0]] = inner_dic
Run Code Online (Sandbox Code Playgroud)

我得到一个明显错误的结果.代码的一个问题是,它覆盖了对.我不知道如何解决这个问题.

Pad*_*ham 5

您可以将defaultdictCounter dict 结合使用:

from collections import Counter, defaultdict
d = defaultdict(Counter)

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b'] ]

for k, v in text:
    d[k][v] += 1 # for single value
   # d[k].update(v) for multiple values i.e list of words

from pprint import pprint as pp

pp(d)
{'a': Counter({'b': 2, 'd': 1}),
'w': Counter({'a': 1})}
Run Code Online (Sandbox Code Playgroud)

defaultdict将创建一个新的键/值配对,其中值为Counter dict,如果键不存在,如果键存在,我们只使用Counter.update更新值,这与dict.update不同,将增加值不覆盖.

使用普通的dict无导入我们可以使用dict.setdefault,它将创建一个新的dict作为每个键的k值,并0为每个子键设置一个默认值v:

d = {}
text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b'] ]

for k, v in text:
    d.setdefault(k, {}).setdefault(v,0)
    d[k][v] += 1
pp(d)
{'a': {'b': 2, 'd': 1}, 'w': {'a': 1}}
Run Code Online (Sandbox Code Playgroud)


Ray*_*ger 5

集合模块使得这样的任务的短期工作.

对计数部分使用计数器(它是一种为缺失值返回0的字典,使其易于+=1用于递增计数).使用defaultdict作为外部字典(它可以自动为每个"第一个"前缀创建一个新计数器):

>>> from collections import defaultdict, Counter
>>> d = defaultdict(Counter)
>>> text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b']]
>>> for first, second in text:
    d[first][second] += 1
Run Code Online (Sandbox Code Playgroud)

以下是使用常规词典的等效词:

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b']]

d = {}
for first, second in text:
    if first not in d:
        d[first] = {}
    inner_dict = d[first]
    if second not in inner_dict:
        inner_dict[second] = 0
    inner_dict[second] += 1
Run Code Online (Sandbox Code Playgroud)

短路或长路可以与json模块完美配合(Counterdefaultdict都是可以进行JSON编码的dicts).

希望这可以帮助.祝你的文字分析好运:-)


rlm*_*lms 5

你应该这样做:

for word in words:
  inner_dic = {}
  for pair in text:
    if pair[0] == word:
      num = text.count(pair)
      inner_dic[pair[1]] = num
  dic[word] = inner_dic
Run Code Online (Sandbox Code Playgroud)

也就是说,您应该执行dic[word]而不是dic[pair[0]],这会将 分配给inner_dic最后一次pair检查中的第一个元素,即使pair[0]不是word

  • 谢谢。这是最好的答案,因为您实际上阅读了我的代码并看到了哪里出错了,而不是使用现成的库从头开始编写一些东西。荣誉! (2认同)