Reputation: 2144
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:
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:
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'. Is there a better way of doing this, without an int
to keep track? 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.
Upvotes: 0
Views: 123
Reputation: 4521
This is C
like way rather than Pythonic
. So if you know C
you can understand it just a few seconds.
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
Upvotes: 0
Reputation: 25207
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
. 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.
Upvotes: 3
Reputation: 1856
Use itertools for this, I find it most elegant and resilient to the number of elements/actions:
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.
Upvotes: 0
Reputation: 1966
Assuming a
list as an input to the function,
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. This is more of a pythonic way i think.
Upvotes: 0
Reputation: 239000
Other option to the existing ones using compination of zip
and iter
(explenation here):
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
Upvotes: 0
Reputation: 122159
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
Upvotes: 0
Reputation: 310307
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
). 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 ;-)
Upvotes: 1