python 列表偏平化 & 生成器+装饰器的解决思路

1、

这两天有个朋友问我,如果列表a = [1,2,[3,4],[[5,6,7]]]  转化成 b=[1,2,3,4,5,6,7]怎么搞? 不能用额外的变量呦。

第一反应是递归呀,思路很清晰。可是!我回到家想了20分钟才拼出来代码。。

a = [1,2,[3,4],[[5,6,7]]]
print a

def func(lst):
    if not lst:
        return []
    for i in lst:
        if isinstance(i, list):
            lst.remove(i)
            return func(i) + func(lst)
        else:
            lst.remove(i)
            return [i] + func(lst)

print func(a)
结果:
D:\projects\myapp>python 1.py
[1, 2, [3, 4], [[5, 6, 7]]]
[1, 2, 3, 4, 5, 6, 7]
递归的思路就是,只要是列表,我就往下一层走。一直走到尽头,就是int的数值咯。

然后把这个数值收集起来+去掉这个数字的递归结果,返回给上一层。
感觉有点像2分。递归不要想,越想越乱,只要记住你到了最后一层,要做什么就行了。


更新于2018年3月31日 星期六:

用生成器,不过也是用到了上述的递归思想。。。

# coding=utf-8
def flatten(nested):
    try:
        # 如果是字符串,那么手动抛出TypeError。
        if isinstance(nested, str):
            raise TypeError
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested


L = ['aaadf', [1, 2, 3], 2, 4, [5, [6, [8, [9]], 'ddf'], 7]]
for num in flatten(L):
    print(num)


2、

这个就吊了,我想了一个晚上还没想出来。

假设有个生成器:

def foo():
    for i in range(10):
        yield i
我们这么调用:

    for i in foo():
        print i
就能不断拿到1至10。

现在请你给foo()加一个装饰器,使其每一次迭代能拿到[1,2]两个元素组成的list。

吊吧,装饰器+生成器,混在一起我还真的有点懵逼。

基本思路:装饰器修饰foo(),返回的应该还是必须个生成器。

def wrapper(func):
    def new_func(*args, **kwargs):
        a = func(*args, **kwargs)  # a还是个生成器
        return a  
    return new_func

@wrapper
def foo():
    for i in range(10):
        print "###",i
        yield i

if __name__ == '__main__':
    for i in foo():
        print i

以上代码只能保证加了装饰器的生成器不会出bug,但是真的不会改装呢,备份下,明天继续研究。

嗯,第二天开始谷歌了,还是没啥思路呢。要不赖皮点,这么写:

# coding=utf-8

def wrapper(gen):
    def new_gen(*args, **kwargs):
        lst = list(gen(*args, **kwargs))
        n = 4
        return [lst[i:i+n] for i in range(0, len(lst), n)]
    return new_gen

@wrapper
def foo():
    for i in range(10):
        yield i


if __name__ == '__main__':
    for i in foo():
        print i
结果:

[0, 1, 2, 3]
[4, 5, 6, 7]
[8, 9]
呵,实现是实现了,就是觉得傻逼。竟然先把这个生成器->list,然后对list等分。感觉这不是正确的解决方案。一定有正确的方法的。

想了下,装饰器返回一个生成器在,这个逻辑是不会错的。

def wrapper(gen):
    def new_gen(*args, **kwargs):
        g = gen(*args, **kwargs)
        while True: 
            a,b,c,d = g.next(),g.next(),g.next(),g.next()
            yield [a,b,c,d]
    return new_gen

@wrapper
def foo():
    for i in range(10):
        yield i


if __name__ == '__main__':
    for i in foo():
        print i
结果:
[0, 1, 2, 3]
[4, 5, 6, 7]
哎,还是不大对的感觉,最后的[8,9]怎么搞?不过思路应该差不多,这里面是一个生成器了呢。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值