【问题标题】:Nested dict throws key error when sorting排序时嵌套的dict抛出关键错误
【发布时间】:2019-06-28 21:04:09
【问题描述】:

我有下面的字典叫nested:

{1: {1: {'x0': Decimal('21.600')}},
 2: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('21.600')}},
 3: {1: {'x0': Decimal('223.560')},
     2: {'x0': Decimal('279.552')},
     3: {'x0': Decimal('290.868')}},
 4: {1: {'x0': Decimal('21.600')}, 2: {'x0': Decimal('223.560')}},
 5: {1: {'x0': Decimal('21.600')}},
 6: {1: {'x0': Decimal('223.560')}},
 7: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('256.896')}},
 8: {1: {'x0': Decimal('223.560')},
     2: {'x0': Decimal('232.307')},
     3: {'x0': Decimal('244.550')},
     4: {'x0': Decimal('253.296')}},
 9: {1: {'x0': Decimal('223.560')},
     2: {'x0': Decimal('277.219')},
     3: {'x0': Decimal('288.064')}},
 10: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('255.648')},
      3: {'x0': Decimal('281.909')},
      4: {'x0': Decimal('288.314')}},
 11: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('259.712')},
      3: {'x0': Decimal('295.884')}},
 12: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('288.064')}},
 13: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('273.152')},
      3: {'x0': Decimal('299.412')}},
 14: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('259.712')},
      3: {'x0': Decimal('295.884')}},
 15: {1: {'x0': Decimal('223.560')}},
 16: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('246.303')},
      3: {'x0': Decimal('272.564')},
      4: {'x0': Decimal('278.969')}},
 17: {1: {'x0': Decimal('223.560')}},
 18: {1: {'x0': Decimal('223.560')}},
 19: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('249.746')},
      3: {'x0': Decimal('260.590')}},
 20: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('239.300')},
      3: {'x0': Decimal('265.560')},
      4: {'x0': Decimal('271.965')},
      5: {'x0': Decimal('294.708')}},
 21: {1: {'x0': Decimal('223.560')}},
 22: {1: {'x0': Decimal('223.560')}},
 23: {1: {'x0': Decimal('223.560')}},
 24: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('273.152')},
      3: {'x0': Decimal('299.412')}},
 25: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('260.868')}},
 26: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('249.746')},
      3: {'x0': Decimal('260.590')}},
 27: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('246.303')},
      3: {'x0': Decimal('272.564')},
      4: {'x0': Decimal('278.969')},
      5: {'x0': Decimal('298.215')}},
 28: {1: {'x0': Decimal('223.560')}},
 29: {1: {'x0': Decimal('223.560')}},
 30: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('295.596')}}

我正在尝试按每个嵌套字典中的 x0 值进行排序。

我只想对“内部”值进行排序,所以对于我的具体示例:

{1: {1: {'x0': Decimal('21.600')}},
 2: {1: {'x0': Decimal('21.600')}, 2: {'x0': Decimal('223.560')}},
 [...]

我正在尝试使用sorted() 方法对其进行排序:

sorted_dict = sorted(nested.values(), key=lambda x: x['x0'])

但是,这给了我以下错误:

KeyError: 'x0'

如您所见,在2 内部,嵌套的dict 已排序。

编辑

为了澄清,我的 dict 实际上包含另一个键:

{1: {1: {'text': 'Hi there!', 'x0': Decimal('21.600')}},
 2: {1: {'text': 'My email is', 'x0': Decimal('223.560')},
     2: {'text': 'example@domain.com', 'x0': Decimal('21.600')}},
 [...]

在实施@Willem 的解决方案时,仅对x0 进行排序,但未对text 键进行排序:

{1: {1: {'text': 'Hi there!', 'x0': Decimal('21.600')}},
 2: {1: {'text': 'My email is', 'x0': Decimal('21.600')},
     2: {'text': 'example@domain.com', 'x0': Decimal('223.560')}},
 [...]

【问题讨论】:

  • 警告:Python 中的字典在 Python 3.7 中只有明确定义的顺序(插入顺序)。在早期版本中,字典的迭代顺序是由实现定义的,因此在解释器之间或同一解释器的版本之间可能会有所不同(甚至对于某些类型的键,如果启用了哈希随机化,甚至调用同一解释器)。如果您想以向后兼容的方式处理有序数据,您可能希望使用列表或元组。
  • @Blckknght:如果我理解正确,值将重新映射到不同的键,因此在原始数据中,字典首先与键 2 关联,现在与键 1 关联。不过,我同意在这里列出一个列表会更有意义。

标签: python python-3.x dictionary


【解决方案1】:

x0 键在 子字典 中定义。所以你不能在外部值上使用sorted(..)对其进行排序。

你可以像这样构造一个字典:

from operator import itemgetter

{k : dict(enumerate(sorted(v.values(), key=itemgetter('x0')), 1))
 for k, v in nested.items() }

我们在这里假设子字典的键具有键 12、...但是使用列表而不是键的字典可能更有意义。

对于给定的样本数据,这给了我们:

{1: {1: {'x0': Decimal('21.600')}},
 2: {1: {'x0': Decimal('21.600')}, 2: {'x0': Decimal('223.560')}},
 3: {1: {'x0': Decimal('223.560')},
     2: {'x0': Decimal('279.552')},
     3: {'x0': Decimal('290.868')}},
 4: {1: {'x0': Decimal('21.600')}, 2: {'x0': Decimal('223.560')}},
 5: {1: {'x0': Decimal('21.600')}},
 6: {1: {'x0': Decimal('223.560')}},
 7: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('256.896')}},
 8: {1: {'x0': Decimal('223.560')},
     2: {'x0': Decimal('232.307')},
     3: {'x0': Decimal('244.550')},
     4: {'x0': Decimal('253.296')}},
 9: {1: {'x0': Decimal('223.560')},
     2: {'x0': Decimal('277.219')},
     3: {'x0': Decimal('288.064')}},
 10: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('255.648')},
      3: {'x0': Decimal('281.909')},
      4: {'x0': Decimal('288.314')}},
 11: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('259.712')},
      3: {'x0': Decimal('295.884')}},
 12: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('288.064')}},
 13: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('273.152')},
      3: {'x0': Decimal('299.412')}},
 14: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('259.712')},
      3: {'x0': Decimal('295.884')}},
 15: {1: {'x0': Decimal('223.560')}},
 16: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('246.303')},
      3: {'x0': Decimal('272.564')},
      4: {'x0': Decimal('278.969')}},
 17: {1: {'x0': Decimal('223.560')}},
 18: {1: {'x0': Decimal('223.560')}},
 19: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('249.746')},
      3: {'x0': Decimal('260.590')}},
 20: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('239.300')},
      3: {'x0': Decimal('265.560')},
      4: {'x0': Decimal('271.965')},
      5: {'x0': Decimal('294.708')}},
 21: {1: {'x0': Decimal('223.560')}},
 22: {1: {'x0': Decimal('223.560')}},
 23: {1: {'x0': Decimal('223.560')}},
 24: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('273.152')},
      3: {'x0': Decimal('299.412')}},
 25: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('260.868')}},
 26: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('249.746')},
      3: {'x0': Decimal('260.590')}},
 27: {1: {'x0': Decimal('223.560')},
      2: {'x0': Decimal('246.303')},
      3: {'x0': Decimal('272.564')},
      4: {'x0': Decimal('278.969')},
      5: {'x0': Decimal('298.215')}},
 28: {1: {'x0': Decimal('223.560')}},
 29: {1: {'x0': Decimal('223.560')}},
 30: {1: {'x0': Decimal('223.560')}, 2: {'x0': Decimal('295.596')}}}

或使用额外的'text' 键:

{1: {1: {'text': 'Hi there!', 'x0': Decimal('21.600')}},
 2: {1: {'text': 'example@domain.com', 'x0': Decimal('21.600')},
     2: {'text': 'My email is', 'x0': Decimal('223.560')}}}

【讨论】:

  • 非常好的解决方案 - 我试过了,它确实适用于密钥 x0 - 但是,嵌套的 dict 还包含一个 text 密钥。我认为只要嵌套的 dict 得到 sortefd,该 dict 中的所有键/值也会得到排序。您是否介意查看我更新的问题,因为我已经进行了编辑?
  • @oliverbj:我不完全确定是否有一个 text 属性这很有意义,因为在 Python-3.6 之前,字典是无序的(最好还是考虑这些概念上无序)。
  • 那么另一种解决方案是什么?将其更改为嵌套列表/元组?这样可以按照我正在寻找的方式进行排序吗?
  • @oliverbj:此外,如果我理解正确,text 实际上与它一起排序。查看更新,如您所见,'example@domain.com 仍然与21.600 相关联,但它现在被放在了第一位。
  • 一定是我打印出了错误的信息。道歉,但我如何打印新的排序字典? {k : dict(...)
猜你喜欢
  • 2017-12-27
  • 2016-01-26
  • 2019-05-20
  • 2019-01-08
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多