我怎样才能在不导入任何东西的情况下以一种富有表现力的单行方式进行分组?

How can I do groupby without importing anything and in an expressive and oneliner kind of way?

我想知道是否可以在不导入任何库的情况下以简单的方式对 python 中的列表进行分组。

输入示例可以是:

a="0 0 1 2 1"

并输出

[(0,0),(1,1),(2)]

我正在考虑类似 itertools groupby 的实现

class groupby:
    # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
    # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
    def __init__(self, iterable, key=None):
        if key is None:
            key = lambda x: x
        self.keyfunc = key
        self.it = iter(iterable)
        self.tgtkey = self.currkey = self.currvalue = object()
    def __iter__(self):
        return self
    def __next__(self):
        self.id = object()
        while self.currkey == self.tgtkey:
            self.currvalue = next(self.it)    # Exit on StopIteration
            self.currkey = self.keyfunc(self.currvalue)
        self.tgtkey = self.currkey
        return (self.currkey, self._grouper(self.tgtkey, self.id))
    def _grouper(self, tgtkey, id):
        while self.id is id and self.currkey == tgtkey:
            yield self.currvalue
            try:
                self.currvalue = next(self.it)
            except StopIteration:
                return
            self.currkey = self.keyfunc(self.currvalue)

但更短

如何使用 a.split(' ') 然后使用 for 循环来做到这一点?

我刚刚知道怎么做。

{k:[v for v in a.split() if v == k] for k in set(a.split())}

[tuple(v for v in a.split() if v == k) for k in set(a.split())]

但是 - 此解决方案不能用于字典,因为字典不可哈希 - 所以这可能是 itertools 实现如此复杂的原因之一。

要按值对项目进行分组(而不是像 itertools groupby 那样按更改分组),您可以使用嵌入字典的列表理解来将数据组织到列表中:

a="0 0 1 2 1"

groups = [ g[v] for g in [dict()] for v in map(int,a.split()) 
           if g.setdefault(v,[]).append(v) or len(g[v])==1  ]

print(groups)

[[0, 0], [1, 1], [2]]

每个列表(内部 (g) 字典中的值)都增加了 a 中的项目,但只返回一次(遇到新的分组键时)。

使用字典对项目进行分组避免了对项目进行排序的需要(如果使用 itertools.groupby 则需要排序)

如果你希望分组完全像groupby一样工作,那么当遇到新键时需要清除内部字典:

groups = [ g.setdefault(v,g.clear() or [v])
           for g in [dict()] for v in map(int,a.split()) 
           if v not in g or g[v].append(v) ]
print(groups)

[[0, 0], [1], [2], [1]]

您可以对其进行扩展以产生与 groupby 相同的输出(包括计算的分组键和使用可迭代对象:

a="0 0 1 2 1"

ia  = map(int,a.split()) # an iterable
key = lambda v: v > 0    # a grouping key function
          
groups = [ (k,g.setdefault(k,g.clear() or [v]))
           for g in [dict()] for v in ia for k in [key(v)]
           if k not in g or g[k].append(v) ]

print(groups)
[(False, [0, 0]), (True, [1, 2, 1])]

请注意,以上所有解决方案都会生成分组项目列表(与 grouby 的项目迭代器相反