首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >返回发电机内部的发电机

返回发电机内部的发电机
EN

Stack Overflow用户
提问于 2022-08-22 08:03:21
回答 5查看 84关注 0票数 0

我有一个整数列表和一个元组列表(表示间隔),我想编写一个方法,对于每个元组,返回包含在区间中的整数的子列表,但是我想用生成器来实现它。

用于下列投入:

代码语言:javascript
复制
l = [1, 2, 3, 4, 5]
intervals = [(1, 2), (2, 4)]

子列表应该是:[1, 2][2, 3, 4]

我的尝试:

代码语言:javascript
复制
def gen_intervals(l, intervals):
    for e in l:
        for i in intervals:
            if e > i[0] and e < i[1]:
                yield e

但是,这将给我一个元素列表,因为生成器一次生成一个元素。我想要的是在这个区间内产生一个元素的生成器。

然后,我会像这样用它:

代码语言:javascript
复制
for interval in gen_intervals(l, intervals):
    for e in interval:
        print(e)

重要信息:

  • 列表是排序的,间隔也是如此(尽管它们可能重叠)。间隔遵循间隔的标准数学表示:左端点,右侧端点和左端点<右端点。对于任意两个区间u,v,它们不能是另一个区间的子集。通过排序,我的意思是它们的右端点按升序排序。
  • 我真的想先迭代元素,然后再迭代一次,因为元素列表可能非常非常长,所以我只想迭代这个列表一次。元素列表的长度是>>,间隔列表的长度,但确切的长度是任意的。
EN

回答 5

Stack Overflow用户

发布于 2022-08-22 09:29:54

您可以简单地在yield行上使用生成器理解:

代码语言:javascript
复制
def gen_intervals(elements, intervals):
    for vmin, vmax in intervals:
        yield (elm for elm in elements if (vmin <= elm <= vmax))

这意味着:

代码语言:javascript
复制
l = [1, 2, 3, 4, 5]
intervals = [(2, 4), (1, 2)]

for interval in gen_intervals(l, intervals):
    for e in interval:
        print(e)
    print()
代码语言:javascript
复制
2
3
4

1
2
票数 2
EN

Stack Overflow用户

发布于 2022-08-22 08:54:17

你可以这样做。每个间隔生成器都有一个缓冲区,当请求项时,它首先刷新缓冲区,然后选择下一个list元素。如果该元素恰好是“它的”元素,则生成它,否则将其放置在相应区间的缓冲区中,然后尝试使用下一个元素。

代码语言:javascript
复制
def items_by_iterval(lst, intervals):
    list_iter = iter(lst)
    buffers = [[] for _ in intervals]

    def interval_iter(n):
        while True:
            if buffers[n]:
                yield from buffers[n]
                buffers[n] = []

            try:
                k = next(list_iter)
            except StopIteration:
                return

            for m, (a, b) in enumerate(intervals):
                if a <= k <= b:
                    if m == n:
                        yield k
                    else:
                        buffers[m].append(k)
                    break

    return [interval_iter(n) for n, _ in enumerate(intervals)]


##

lst = [1, 9, 2, 8, 3, 7, 4, 6, 5, 1, 9, 2, 8, 3, 7, 4, 6, 5, ]
intervals = [(5, 7), (2, 4), (8, 10)]

for ii in items_by_iterval(lst, intervals):
    for k in ii:
        print(k, end=' ')
    print()

这些指纹:

代码语言:javascript
复制
7 6 5 7 6 5
2 3 4 2 3 4
9 8 9 8
票数 0
EN

Stack Overflow用户

发布于 2022-08-22 09:01:20

与任何for循环不同,您可以使用map为每个间隔的每个元素创建一个具有TrueFalse值的列表。然后,您可以使用itertools.compress创建一个迭代器对象,该对象生成在各自间隔内的元素:

代码语言:javascript
复制
import itertools

l = [1, 2, 3, 4, 5]
intervals = [(2, 4),]
for interval in intervals:
    # use range(i+1, j) to check if element is in interval
    mapped = map(lambda el: el in range(interval[0] + 1, interval[1]), l)
    # mapped = [False, False, True, False, False]
    res = itertools.compress(l, mapped)  # save this in case of more intervals

print(next(res))  # returns 3
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73441900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档