0

基本上我想要做的是获取两个对象列表并根据一些测试并将它们分为两个列表,具体取决于结果是True还是False. filter()除了确定它是进还是出之外,它决定了要转到哪个列表/迭代器,而不是确定它是做什么的。我已经尝试使用itertools.groupby()

import random
from itertools import groupby

class FooObject(object):
    def __init__(self):
        self.key = random.choice((True, False))

    def __repr__(self):
        return '<Foo: %s>' % self.key

foos = [FooObject() for _ in range(10)]
left, right = [], []

groups = groupby(sorted(foos, key=lambda o: o.key), lambda o: o.key)
for k, group in groups:
    if k:
        right = list(group)
    else:
        left = list(group)

print left
print right

这可以完成工作,但只是想知道是否有更清晰/更简单的方法。我意识到我可以使用filter()(或等效的列表理解)并在两遍中完成,但这有什么乐趣呢?

4

2 回答 2

1

这是一个函数,它只使用一次源并返回一个类似字典的对象,它的每个成员都是一个生成器,它尽可能地从源中产生值:

def partition(it, fun):

    class x(object):
        def __init__(self):
            self.buf = {}

        def flush(self, val):
            for p in self.buf.get(val, []):
                yield p
            self.buf.pop(val, None)

        def __getitem__(self, val):
            for p in self.flush(val): yield p
            while True:
                try:
                    p = next(it)
                except StopIteration:
                    break
                v = fun(p)
                if v == val:
                    yield p
                else:
                    self.buf.setdefault(v, []).append(p)
            for p in self.flush(val): yield p

    return x()

使用示例:

def primes(): # note that this is an endless generator
    yield 2
    p, n = [], 3
    while True:
        if all(n % x for x in p):
            p.append(n)
            yield n
        n += 2


p = partition(primes(), lambda x: x % 3)
# each member of p is endless as well

for x in p[1]:
    print x
    if x > 200: break

for x in p[2]:
    print x
    if x > 200: break
于 2013-02-11T22:16:24.773 回答
1

如果你只有 2 个桶,你可以使用三元:

d={'left':[],'right':[]}
for e in (random.random() for i in xrange(50)):
    d['left' if e<0.5 else 'right'].append(e)

如果存储桶超过 2 个,请使用返回已定义键的函数或使用带有列表的默认字典:

def f(i):
   return int(i*10)

DoL=defaultdict(list)
for e in (random.random() for i in xrange(50)):
   DoL[f(e)].append(e)
于 2013-02-11T23:11:07.910 回答