简体   繁体   English

如何对迭代器进行操作,然后对python中的下一个迭代器进行其他操作

[英]How to do something to an iterator, then something else to the next iterator in python

What's the 'correct' python way of doing something to the first element, but something else to the second, and something different again for the third in a list, then repeat, eg: 对列表中的第一个元素执行某种操作,对第二个元素进行其他操作,对列表中的第三个元素进行其他操作的“正确” python方法是什么,然后重复执行,例如:

a = [2, "foo1", "bar1", 5, "foo3", "bar2", 3, "foo2", "bar3"]
my_function(a)

should give 应该给

20
foo1
foobar1
50
foo3
foobar2
30
foo2
foobar3

where "my_function" would be something like: 其中“ my_function”类似于:

def my_function(a):
    i = 0
    for line in a:
        if i == 0:
            line = line*10
        if i == 2:
            line = "foo"+line
        i = i + 1
        if i == 3:
            i = 0
        print line

But this looks very 'unpython'. 但这看起来非常“ unpython”。 Is there a better way of doing this, without an int to keep track? 是否有这样做,没有更好的办法int跟踪? A way of saying, the first time I call this function, do this but the second time, do this, then the third time, do this, then go back to the beginning and do what you did first. 可以这样说,我第一次调用此函数,但是第二次调用此函数,然后第三次调用此函数,然后回到开始并首先执行操作。 A function that keeps track of how many times it has been called. 跟踪已调用次数的函数。

Working with an iterator, you can do like this: 使用迭代器,您可以执行以下操作:

def my_function(a):
    a = iter(a)
    while True:
        yield 10 * next(a)    
        yield next(a)
        yield "foo" + next(a)

a = [2, "foo1", "bar1", 5, "foo3", "bar2", 3, "foo2", "bar3"]    
print list(my_function(a))
#prints [20, 'foo1', 'foobar1', 50, 'foo3', 'foobar2', 30, 'foo2', 'foobar3'] 

If anyone is wondering what happens at the end of the list, next(a) will raise StopIteration . 如果有人想知道列表末尾会发生什么, next(a)将引发StopIteration The exception terminates the generator my_function , but code that iterates over it -- in this case list() -- will recognize it as a normal end of iteration. 异常终止生成器my_function ,但是对其进行迭代的代码(在本例中为list()会将其识别为正常的迭代结束。

I might do something like: 我可能会做类似的事情:

def my_function(lst):
    items = (lst[i:i+3] for i in xrange(0, len(lst), 3))
    for group in items:
       yield group[0] * 10
       yield group[1]
       yield 'foo' + group[2]

Running on your input: 在您的输入上运行:

>>> list(my_function(a))
[20, 'foo1', 'foobar1', 50, 'foo3', 'foobar2', 30, 'foo2', 'foobar3']

I've made 2 big assumptions here -- that your list is indeed a list (or at least a sequence), and that the length of the sequence is divisible by 3 (otherwise you'll end up with an IndexError ). 我在这里做了两个大假设-您的列表确实是一个列表(或至少一个序列),并且序列的长度可以被3整除(否则,您将得到IndexError )。 Both of these assumptions could be taken care of without too much effort, but I'll leave that as an exercise if you're really interested ;-) 无需过多的努力就可以解决这两个假设,但是如果您真的有兴趣,我将其保留为练习;-)

You could use something like: 您可以使用类似:

def my_function (a):
    actions = [lambda l: l * 10,
               lambda l: l,
               lambda l: "foo" + l]
    for i, line in enumerate(a):
        line = actions[i % 3](line)
        print line

Other option to the existing ones using compination of zip and iter (explenation here ): 使用zipiter组合的现有选项的其他选项( 在此处进行说明 ):

def my_function2(a):
    for v1,v2,v3 in zip(*[iter(a)]*3):
        print(v1*10,v2, 'foo'+ v3)

% gives
20 foo1 foobar1
50 foo3 foobar2
30 foo2 foobar3

Use itertools for this, I find it most elegant and resilient to the number of elements/actions: 为此使用itertools ,我发现它对元素/动作的数量最为优雅和有弹性:

import itertools


def my_function(a):
    actions = itertools.cycle(
        (lambda l: l * 10, lambda l: l, lambda l: "foo" + l)
    )

    for val, action in itertools.izip(a, actions):
        yield action(val)

a = [2, "foo1", "bar1", 5, "foo3", "bar2", 3, "foo2", "bar3", 7]
print list(my_function(a))

Result: 结果:

[20, 'foo1', 'foobar1', 50, 'foo3', 'foobar2', 30, 'foo2', 'foobar3', 70]

As you can see from the example, this will work even if the elements count is not a multiplication of the actions count (or even less than actions count). 从示例中可以看到,即使元素计数不是操作计数的乘积(甚至小于操作计数)也可以使用。

This is python2 version, if you need 3 please specify. 这是python2版本,如果需要3,请指定。

Assuming a list as an input to the function, 假设a列表作为输入的功能,

def my_function(a):
   a[::3] = map(lambda x: 10*x, a[::3])
   a[2::3] = map(lambda x: "foo"+x, a[2::3])

Here I am making use of extended slices in python. 在这里,我正在使用python中的扩展片 This is more of a pythonic way i think. 我认为这更多是一种Python方式。

This is C like way rather than Pythonic . 这是类似于C方式,而不是Pythonic So if you know C you can understand it just a few seconds. 因此,如果您了解C ,那么只需几秒钟即可了解它。

def my_function(a):
    for n, line in enumerate(a):
        if n % 3 == 0:
            line = line * 10
        elif n % 3 == 2:
            line = "foo" + line
        print line

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM