Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在键上连接python迭代器_Python_Iterator - Fatal编程技术网

在键上连接python迭代器

在键上连接python迭代器,python,iterator,Python,Iterator,我正在寻找一种连接python迭代器的方法,如itertools.izip_longest()可以,但我希望连接具有相同“键”(由参数定义)的元素,并在所有迭代器上都不存在键时输出None。我假设迭代器按“键”升序排序 例如: iter1 = iter((1, 3, 4, 9)) iter2 = iter((3, 5, 6)) iter3 = iter((1, 3, 10)) zipjoiner(iter1, iter2, iter3) 应提供: iter(((1, None, 1), (3

我正在寻找一种连接python迭代器的方法,如
itertools.izip_longest()
可以,但我希望连接具有相同“键”(由参数定义)的元素,并在所有迭代器上都不存在键时输出
None
。我假设迭代器按“键”升序排序

例如:

iter1 = iter((1, 3, 4, 9))
iter2 = iter((3, 5, 6))
iter3 = iter((1, 3, 10))

zipjoiner(iter1, iter2, iter3)
应提供:

iter(((1, None, 1), (3, 3, 3), (4, None, None), (None, 5, None), (None, 6, None), (9, None, None), (None, None, 10)))
(在本例中,键是默认标识
lambda x:x

我试图修改中的
izip_longest()
实现,它可以工作(至少在我的示例中是这样),但我正在寻找一个更优雅的解决方案。 有什么想法吗

这是我的代码:

def zipjoiner(*args, **kwds):
    # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
    fillvalue = kwds.get('fillvalue')
    key = kwds.get('key', lambda x: x)
    counter = [len(args) - 1]
    def sentinel():
        if not counter[0]:
            raise ZipExhausted
        counter[0] -= 1
        yield fillvalue
    fillers = itertools.repeat(fillvalue)
    iterators = [itertools.chain(it, sentinel(), fillers) for it in args]

    def getkey(x):
        return None if x is None else key(x)

    try:
        while iterators:
            elements = tuple(map(next, iterators))
            keys = tuple(map(getkey, elements))
            minkey = min(_ for _ in keys if not _ is None)
            while not all(k == minkey for k in keys):
                yield tuple(map(lambda (k, v): v if k == minkey else None, zip(keys, elements)))
                elements = tuple(map(lambda (k, it, v): it.next() if k == minkey else v, zip(keys, iterators, elements)))
                keys = tuple(map(getkey, elements))
                minkey = min(_ for _ in keys if not _ is None)
            yield elements

    except ZipExhausted:
        pass

如果不想保持顺序,可以将列表转换为集合,然后循环遍历所有输入迭代器中所有值的排序列表,并根据值是否在相应的集合中生成一个有值或无值的元组:

def join_iterators(*iterators):
    sets = []
    for iterator in iterators:
        sets.append(set(iterator))

    values = set(itertools.chain(*iterators))
    get_value_or_none = lambda value, s: value if value in s else None
    for value in sorted(values):
        yield tuple(get_value_or_none(value, s) for s in sets)

这并没有解决您的关键功能,但我认为您已经找到了如何应用它的方法;)

虽然你可以做一些可读性更好的东西,但我认为你不能做一些效率更高的东西

从可读性的角度来看,我将更改标题和前几行:

def zipjoiner(*iters, fillvalue=None, key=lambda x: x):
    # drop first two lines dealing with fillvalue and key
因为没有理由处理
**kwds