-1

我是字典新手,在理解如何将文件的输出解释为字典并读取它的键值对时遇到了麻烦。

这是我的脚本,它将文件的输出作为字典:

dicts = {}
for line in sys.stdin:
   d = ast.literal_eval(line)
   for k,v in d.items():
      dicts.setdefault(k, []).append(v)
      charcount = sum(int(d['charcount']) for d in dicts[k])
      output_dict = {k: {'charcount': charcount}}
      print output_dict

这是脚本作为输入的文件的输出:

{ 262968617233162240 : {'@': False, '#': False, 'word': 'good#1st#time#will',    'longword': True, 'title': False, 'charcount': 18, 'uppercase': False, 'stop': False, 'sscore': False, 'url': False, '!!!': False} }
{ 262968617233162240 : {'@': False, '#': False, 'word': 'be', 'longword': False, 'title': False, 'charcount': 2, 'uppercase': False, 'stop': True, 'sscore': False, 'url': False, '!!!': False} }
{ 262968617233162240 : {'@': False, '#': False, 'word': 'going', 'longword': False, 'title': False, 'charcount': 5, 'uppercase': False, 'stop': False, 'sscore': False, 'url': False, '!!!': False} }
{ 262968617233162240 : {'@': False, '#': False, 'word': 'back#', 'longword': False, 'title': False, 'charcount': 5, 'uppercase': False, 'stop': False, 'sscore': False, 'url': False, '!!!': False} }
{ 263790847424880641 : {'@': False, '#': False, 'word': 'http://instagr.am/p/rx9939civ8/\xc2\xa0', 'longword': True, 'title': False, 'charcount': 33, 'uppercase': False, 'stop': False, 'sscore': False, 'url': True, '!!!': False} }

当我运行脚本时,我得到了重复的值,而不是解析整个输入。

谢谢。

4

2 回答 2

1

我怀疑您在这里实际寻找的不是一个大字典,而是一个字典列表,每行一个。例如:

dicts = []
for line in sys.stdin:
    dicts.append(eval(line))

我实际上会用ast.literal_eval(如eval)文档建议的那样写这个,* 并将其简化为列表理解:

dicts = [ast.literal_eval(line) for line in sys.stdin]

但无论哪种方式,现在每个元素dicts都是一个字典。因此,将它们全部打印出来:

for d in dicts:
    print d

唯一的事情是,你想对它们进行排序。我不确定你想如何对它们进行排序一般来说,排序字典没有任何意义(这就是为什么 Python 2 给你一个无意义的顺序,而 Python 3 给你一个TypeError)。当然,在某些特殊情况下存在某种有意义的顺序,但每种情况都是不同的。

也许在您的情况下,您想依靠每个 dict 都有一个键的事实,并按该键排序?如果是这样:

for d in sorted(dicts, key=lambda d: d.keys()[0]):
    print d

但这只是一个猜测。


来自评论:

我如何计算所有具有相同键的字典的字符计数(它存在于字典的值部分)。

如果你想这样做,你有两个选择。

首先,您可以随时搜索整个字典列表,如下所示:

charcounts = []
for d in dicts:
    for k, v in d.items():
        if k == key:
            charcounts.append(v['charcount'])

但在这种情况下,使用“multidict”结构可能会更好——也就是说,一个 dict 其值都是列表(在这种情况下是 dicts)。

有两种简单的方法来构建多字典——setdefault方法 ondictdefaultdict类 in collections。两者都同样简单;不同的是,第一个给你一个常规dict的,所以它是一个KeyError寻找一个不存在的键,而第二个给你一个defaultdict,所以你会得到一个空列表来寻找一个不存在的键存在。我会展示第一个,但实际上,你必须决定你想要哪个。

dicts = {}
for line in sys.stdin:
    d = ast.literal_eval(line)
    for k, v in d.items(): # should only be one
        dicts.setdefault(k, []).append(v)

这需要更多的设置工作,但需要较少的搜索工作。例如,上面的整个混乱可以用一行代替:

charcounts = [d['charcount'] for d in dicts[key]]

…而且,如果dicts很大,它会快很多,因为它只需要查看匹配键的那些,而不是所有的。

为了让您了解这是什么样子,以下是dicts您的示例输入:

{262968617233162240: 
    [
        {'!!!': False, '#': False, '@': False, 'charcount': 18, 'longword': True, 'sscore': False, 'stop': False, 'title': False, 'uppercase': False, 'url': False, 'word': 'good#1st#time#will'},
        {'!!!': False, '#': False, '@': False, 'charcount': 2, 'longword': False, 'sscore': False, 'stop': True, 'title': False, 'uppercase': False, 'url': False, 'word': 'be'},
        {'!!!': False, '#': False, '@': False, 'charcount': 5, 'longword': False, 'sscore': False, 'stop': False, 'title': False, 'uppercase': False, 'url': False, 'word': 'going'},
        {'!!!': False, '#': False, '@': False, 'charcount': 5, 'longword': False, 'sscore': False, 'stop': False, 'title': False, 'uppercase': False, 'url': False, 'word': 'back#'}
    ],
 263790847424880641: 
    [
        {'!!!': False, '#': False, '@': False, 'charcount': 33, 'longword': True, 'sscore': False, 'stop': False, 'title': False, 'uppercase': False, 'url': True, 'word': 'http://instagr.am/p/rx9939civ8/\xc2\xa0'}
    ]
}

从另一条评论:

所以我正在寻找的输出是:{ 262968617233162240, charcount: 30}

好吧,这在 Python 中是无效的。它看起来像是介于集合和字典之间的东西。dict 是一组键值对,每个键和值之间有一个冒号。

在 Python 中有效的东西:

{262968617233162240: {'charcount': 30}}

你怎么得到那个?

好吧,我已经向您展示了如何获取任何给定键的字符计数列表。在将它们相加之前,您必须将它们全部转换为数字:

charcounts = [int(d['charcount']) for d in dicts[key]]

然后,要将它们相加,只需调用sum

charcount = sum(int(d['charcount']) for d in dicts[key])

现在,我们如何构建您想要的输出?

charcount = sum(int(d['charcount']) for d in dicts[key])
output_dict = {key: {'charcount': charcount}}

如果您想对 multidict 中的每个键执行此操作:

for key, values in dicts.items():
    charcount = sum(int(d['charcount']) for d in values)
    output_dict = {key: {'charcount': charcount}}
    # now do something with output_dict

* 或者,更好的是,更改保存代码以使用实际用于数据交换的格式,例如JSONpickle

于 2013-10-31T00:24:08.703 回答
0

你有两个主要问题:

1)

print dicts[v]

不能作为 dict 使用键调用,而 v 是值。这个电话应该给你(你的价值观实际上是字典):

TypeError: unhashable type: 'dict'

改变它

print dicts[k]

程序将运行

2)

文件中的前三行具有相同的键。因此,当您更新字典时,它们会被覆盖。所以最后你只有两个输出(四行,因为它包括两个打印调用):

{'@': False, 'uppercase': False, 'stop': False, '!!!': False, '#': False, 'word': 'back#', 'longword': False, 'title': False, 'url': False, 'sscore': False, 'charcount': 5}
262968617233162240 {'@': False, 'uppercase': False, 'stop': False, '!!!': False, '#': False, 'word': 'back#', 'longword': False, 'title': False, 'url': False, 'sscore': False, 'charcount': 5}
{'@': False, 'uppercase': False, 'stop': False, '!!!': False, '#': False, 'word': 'http://instagr.am/p/rx9939civ8/\xc2\xa0', 'longword': True, 'title': False, 'url': True, 'sscore': False, 'charcount': 33}
263790847424880641 {'@': False, 'uppercase': False, 'stop': False, '!!!': False, '#': False, 'word': 'http://instagr.am/p/rx9939civ8/\xc2\xa0', 'longword': True, 'title': False, 'url': True, 'sscore': False, 'charcount': 33}
Script terminated.
于 2013-10-30T23:31:11.433 回答