4

我正在尝试使用生成器压缩列表:

例子

[1, 1, 1, 1, 2, 2, 2, 1, 1, 1] == [1, 2, 1]

[5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0])) == [5, 4, 5, 6, 5, 7, 8, 0]

我尝试使用生成器检查第一个和第二个元素是否相等,然后检查第二个和第三个等等,直到它不再相等“当它达到 4”然后产生“5”然后它会重复这个过程开始“4”

代码

test = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0] # sample list
from typing import Iterable
def compress(items: list) -> Iterable:

    x = 0
    while items[x] == items[x + 1]:
        x += 1
    yield items[x]


ans = compress(test)
for x in ans:
    print(ans)

但我一直在

生成器对象压缩在 0x00000254D383C820。为什么它不会循环?

如果我尝试使用 next() 它只会上升到 5 并且不会检查其他数字。

非常感谢任何帮助。

4

6 回答 6

12

正如其他人所解释的那样,您的结构不正确-您只会在循环外遇到产量。理想的方法是迭代成对的连续数字,如果它们不同,则产生循环中的第一个数字。

但是,这是一个规范的方法,通过itertools.groupby它可以删除连续的重复项:

from itertools import groupby 
from operator import itemgetter

list(map(itemgetter(0), groupby(l)))
# [1, 2, 1]
于 2020-05-31T21:18:46.000 回答
4

如果您正在寻找与此相同的效果,请查看该itertools.groupby功能。使用内置工具更聪明。

如果您对学习生成器感兴趣,请编写它。除了在错误的级别上“屈服”之外,您没有犯任何错误,但是您编写了非 Pythonic 代码。跟踪 x 和 x+1 并将整个事情保存在内存中都是不好的。

class NeverInList: pass


from typing import Iterable
def compress(items: list) -> Iterable:
    previous = NeverInList()  # Something never in a list, duh. 
    for item in items:
        if item != previous:
            yield item
            previous = item


ans = compress(test)
for x in ans:
    print(x)   # "x", not "ans"
于 2020-05-31T21:19:03.070 回答
4

所以有几个缺陷,所有这些缺陷都被描述为对问题帖子的评论。

  • 缺少一个会产生多个值的循环
  • 你 printans而 not x,这在逻辑上是生成器对象。

这段代码对你有用吗?

test = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0]

def compress(items):
    for i, d in enumerate(items[:-1]):
        if d == items[i+1]:
            continue
        yield d
    yield items[-1]

for x in compress(test):
    print(x)
于 2020-05-31T21:19:46.583 回答
2

您需要实现stack,并查看列表的最后一个元素是否与值相同

test = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0]

def funct(lis):
    l = []
    for val in lis:
        if len(l) ==0:
            l.append(val)
            yield val
        if l[-1] != val:
            l.append(val)
            yield val


for result in funct(test):
    print(result)

输出

5
4
5
6
5
7
8
0

方式二,使用comparison variableO(N) 时间复杂度和 O(1) 空间复杂度

def funct(lis):
    checker = None
    for val in lis:
        if checker != val:
            checker = val 
            yield val
于 2020-05-31T21:20:39.477 回答
2

呵呵,我从某个地方认出了这个问题。;)

我采取了与您不同的方式,但我认为您可能会发现窥视它很有用:

def compress(i:list):
    return[i[x]for x in range(len(i))if x==0 or i[x-1]!=i[x]]

其他答案更适合您的问题的具体情况,我只是碰巧认识到了设置,并认为我会挖掘并提供我为同样的问题提供的解决方案。干杯!

于 2020-05-31T21:26:32.480 回答
2

另一种解决方案:通过列表和相同列表的组合,移动一个(换句话说,通过连续项目对)并从每对中选择第二个项目,其中第一个(前一个)项目与第二个不同(下一个)项目:

l = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0]
[l[0]] + [y for x,y in zip(l, l[1:]) if x!=y]
#[5, 4, 5, 6, 5, 7, 8, 0]

顺便说一句,这是迄今为止提出的最快的解决方案之一。

于 2020-05-31T22:02:10.950 回答