【问题标题】:Breaking a list in to parts by subject按主题将列表分成几部分
【发布时间】:2013-08-15 22:33:09
【问题描述】:

我有一个字典列表。可以假设每个列表都有相同格式的字典。我们称之为格式:

dict_sample={'a':0,'b':1}

我们还假设a 是一个随机整数,而 b 可以是几个数字之一(或字符串,就此而言)。我想按b 对所有a 值进行排序。例如,如果我有一个如下列表:

a    b
54   1
25   0
53   1
532  2
132  0

list=[{'a':54,'b':1},{'a':25,'b':0},{'a':53,'b':1},{'a':532,'b':2},{'a':132,'b':0}]

我想将其分解为 3 个列表。列表将包括(顺序不重要)

0 list-> [25,132]
1 list-> [54,53]
2 list-> [532]

我知道我可以将列表中的所有a 分解如下,但我无法找到一个优雅的解决方案来按ba 进行排序。有什么建议么?到目前为止,我的代码如下所示:

[row['a'] for row in list]

我想要的是这样的:

index=0      #This could be looped through, or just chosen for one specific value
[row['a'] if row['b']==index for row in list]

【问题讨论】:

  • 你为什么不只拥有(a, b) 元组?
  • 我真正的字典有点长,我不想记住它们的索引方案是什么。我宁愿给每个值一个名字。
  • (a, b) namedtuples 可能会有用。
  • 你不能循环遍历列表中的每个字典并根据 b 的值添加到正确的子列表中吗?或者我在这里错过了什么? IE。为 b 的每个值创建一个列表。循环浏览所有字典。 if(b == "type1"),将a 添加到 type1 列表。等等

标签: python list python-3.x


【解决方案1】:
from collections import defaultdict

data=[{'a':54,'b':1},{'a':25,'b':0},{'a':53,'b':1},{'a':532,'b':2},{'a':132,'b':0}]

output = defaultdict(list)

for d in data:
    output[d['b']].append(d['a'])

output = sorted((k, v) for k, v in output.items())

print output

输出:

[(0, [25, 132]), (1, [54, 53]), (2, [532])]

【讨论】:

  • 这比我拥有的要好得多。
  • 这也很漂亮!
  • 这给了你一个(默认)dict而不是一个列表,这当然意味着它不是按排序顺序的......但是你总是可以使用相应的键作为排序键对dict的值进行排序,在多一行。
  • @abarnert:没有看到排序要求 - 现在它也被排序了。
【解决方案2】:

如果您已经知道所有 b 值,这将是微不足道的。您需要每个 b 值的列表,其中每个字典中的所有 a 值都具有该 b 值。您几乎可以直接将其从英语翻译成理解:

[[d['a'] for d in lst if d['b']==b] for b in bs]

您没有 b 值,但您只需通过另一遍即可获得它们:

bs = (d['b'] for d in lst)

除了你显然只想要唯一的值,并且你想按排序顺序迭代它们,所以:

bs = sorted(set(d['b'] for d in lst))

仅此而已。放在一起:

>>> lst=[{'a':54,'b':1},{'a':25,'b':0},{'a':53,'b':1},{'a':532,'b':2},{'a':132,'b':0}]
>>> bs = sorted(set(d['b'] for d in lst))
>>> [[d['a'] for d in lst if d['b']==b] for b in bs]
[[25, 132], [54, 53], [532]]

【讨论】:

  • 我所要做的就是将if 放在for 循环之后。叹。感谢您指出我的出路错误!
  • @PearsonArtPhoto:啊,我明白你哪里出错了。当你第一次看到多子句推导时,很多人期望它是由内向外的顺序——最里面的表达式在左边,所以它必须从右到左嵌套,对吧?但是不,最里面的表达式是特殊的并且在最前面,但是子句从左到右嵌套。 (这很难在评论中解释,但我怀疑您已经掌握了基本概念,如果您需要详细信息,可以阅读参考文档,希望......)
  • 这当然比它更有意义。将不得不继续尝试变薄。谢谢!
  • @PearsonArtPhoto:如果你练习复杂理解和等效循环代码之间的映射(如果你迷路了,请参考参考文档和/或反复试验),来回几次之后,它应该突然在你的脑海中响起,从它们开始,多子句的理解是显而易见的(除了那些太长而无法在你的脑海中解析的......但英语也是如此,就像在英语中你应该'不要写太长而无法在脑海中解析的语句,例如这个)。
【解决方案3】:

一个可行(且紧凑)的解决方案是:

output= { ok: [ ie['a'] for ie in list if ie['b'] == ok ] for ok in { e['b'] for e in list } }

请注意,{ e['b'] for e in list } 是一个集合理解(该语言相对较新的特性)。大致相当于set([ e['b'] for e in list ])

我在 CPython 3.3.2 上对其进行了测试,它产生的结果完全符合预期,除了字典中的结果。恕我直言,这些列表在字典中比在其他地方更有用,但要符合这个问题:

list_0= output[0]
list_1= output[1]
list_2= output[2]

【讨论】:

    【解决方案4】:
    mylist=[{'a':54,'b':1},{'a':25,'b':0},{'a':53,'b':1},{'a':532,'b':2},{'a':132,'b':0}]
    
    >>> zerolist, onelist, twolist = [], [], []
    >>> for x in mylist:
    
            if 0 in x.values():
                zerolist.append(x['a'])
            elif 1 in x.values():
                    onelist.append(x['a'])
            elif 2 in x.values():
                    onelist.append(x['a'])
    >>> >>> zerolist
    [25, 132]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-16
      • 1970-01-01
      相关资源
      最近更新 更多