根据属性值将列表拆分为子列表

use*_*203 3 python list

我有一个具有suit属性的对象数组,我想根据对象具有的子数组拆分成子数组.我目前正在使用这个:

    for c in cards:
        if c.suit.value == 0:
            spades.append(c)
        elif c.suit.value == 1:
            diamonds.append(c)
        elif c.suit.value == 2:
            clubs.append(c)
        else:
            hearts.append(c)
Run Code Online (Sandbox Code Playgroud)

我尝试使用itertools.groupby如下:

suits = [list(g) for g in intertools.groupby(cards, lambda x: x.suit.value)]
Run Code Online (Sandbox Code Playgroud)

但这只是收益:

[[3, <itertools._grouper object at 0x000000000296B2E8>], ...]
Run Code Online (Sandbox Code Playgroud)

我的第一种方法是有效的,我只想象有一个简单的pythonic one liner可以完成我的需要.

Jea*_*bre 6

迭代时,itertools.groupby产生tuple对象:键和分组值的可迭代对象(允许对数据进行惰性评估)。

您只是将 the 转换tuple为 a list,这不是很有用。

相反,您需要删除密钥(例如通过将其解压到_,pythonic 方式告诉您没有使用它)并强制对值进行迭代:

[list(g) for _,g in itertools.groupby(cards, lambda x: x.suit.value)]
Run Code Online (Sandbox Code Playgroud)

现在,如果您想进行分组排序,仅仅为了创建单行(单行很好,但我更喜欢快速程序)的乐趣而传递sorted(cards)给它并不是很有效groupby。您的方法有效,或者您也可以使用collections.defaultdict,甚至使用间接命名以正确的颜色命名 dict,例如:

import collections

cards = collections.defaultdict(list)
colors = ["spades","diamonds","clubs","hearts"]

for c in cards:
    cards[colors[c.suit.value]].append(c)
Run Code Online (Sandbox Code Playgroud)


Wil*_*sem 5

虽然它不是单行,但通过使用列表,我们使它更优雅:

spades, diamonds, clubs, hearts = collcard = [[] for _ in range(4)]

for c in cards:
    collcard[c.suit.value].append(c)
Run Code Online (Sandbox Code Playgroud)

因此,我们在这里初始化一个包含四个空子列表的列表,然后我们将该卡附加c到带索引的列表中c.suit.value.

我们使用迭代拆包的第一要素分配spades,第二个diamonds,等等.

优点是我们避免排序(在O(n log n)中工作).因此该算法具有时间复杂度O(n)(给定列表追加的摊销成本为O(1)).

虽然oneliner通常是优雅的,但是不应该花费太多精力来写这些内容,因为oneliner可能更难理解,或者对性能有重大影响.