2

In another thread (Python splitting list based on missing numbers in a sequence) I found this solution:

data = [1,  4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]

for k, g in groupby(enumerate(data), lambda (i,x):i-x):
    print map(itemgetter(1), g)

I am new to Python and tried to adapt it to Python 3.4:

for k, g in groupby(enumerate(data), lambda i,x :i-x):
    print('%s' % list(map(itemgetter(1), g)))

I am getting this error:

<lambda>() missing 1 required positional argument: 'x'

My (limited) understanding is that the key function in the groupby statement is still linked to the lambda function requiring two arguments. Is that right? More importantly, is there a way to adapt the above code? It is a very elegant and compact solution.

Georgy
  • 12,464
  • 7
  • 65
  • 73
deckard
  • 852
  • 10
  • 15

1 Answers1

5

My answer is a little late, but I hope that maybe it will be helpful for the future. Yes, you are right. The problem with the translation from Python 2 --> Python 3 is the fact that lambdas in Python 3 do not accept tuples as arguments. However, there is a solution and this is done by having the expected sequence argument bound to a single parameter and then indexing on that parameter :

lambda (i,x):i-x

will become :

lambda x: x[1]-x[0]

Therefore, the code which works in Python 3 will be :

from operator import itemgetter
import itertools
# Find runs of consecutive numbers using groupby.  The key to the solution
# is differencing with a range so that consecutive numbers all appear in
# same group.
L = [ 1,  4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
for k, g in itertools.groupby( enumerate(L), lambda x: x[1]-x[0] ) :
  print (list(map(itemgetter(1), g)))

which will output :

[1]
[4, 5, 6]
[10]
[15, 16, 17, 18]
[22]
[25, 26, 27, 28]

Please see more about lambda with tuples here : python3-equivalent-for-auto-tuple-unpacking-in-lambda

Community
  • 1
  • 1
btrif
  • 307
  • 5
  • 13