0

I have a nested list which contains an integer as the last element of each list, and I am trying to see if the next item in the list is one more than the current item, i.e. if the last element of the current list is 104, if the last element of the next list is 105, do something.

data=[[a,b,c,1200],[a,g,x,3401],[f,a,c,3402],[f,a,c,3403]etc]
for item in data:
    if next(item[-1])==item[-1]+1: #if next item is this item plus one
        #do something

This keeps raising TypeError: Can't convert 'int' object to str implicitly and I don't know why. Is there a way to use addition to compare list elements in python that I'm not aware of?

(The next(item) part might not be accurate, as I'm using a function to get previous and next items in the full code, not next(), but it is the same in principle)

Snaaa
  • 256
  • 1
  • 3
  • 14

3 Answers3

2

Your error message is due to the fact that you used item[1] where you seem to intend item[-1]. However, fixing this won't fix your code – next(item[-1]) does not make sense. I'd suggest to refactor this loop using itertools.groupby():

from itertools import groupby, count
c = count()
for key, group in groupby(data, lambda x: x[-1] - next(c)):
    for item in group:
        # whatever

This will partition data into groups of continuous runs of integers in the last element of the sublists. Each inner loop will run over a separate continuous run, and you can add setup code before this inner loop if needed.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Whoops, that's a typo, it should be item[-1]. I;m using nosklo's answer from http://stackoverflow.com/questions/1011938/python-previous-and-next-values-inside-a-loop to get the next items – Snaaa Aug 03 '12 at 11:53
  • @Snaaa: The point of my answer is that you don't need access to the previous and next item to detect continuous runs, so regardless of your typo this answer should provide an alternative approach to solve your problem. – Sven Marnach Aug 03 '12 at 11:56
  • 1
    Wow, what a marvellous use of `groupby` and `count`. Amazing. – Lauritz V. Thaulow Aug 03 '12 at 11:56
  • Thanks for the help! I'm just wondering: how does it see if the last element of the next list is the current element+1, i.e. 101,102? I may just be misundertsanding the code – Snaaa Aug 03 '12 at 12:00
  • @Snaaa: By subtracting a counter that is increased by one for each iteration from the values, continuous runs of integers are transformed to constant runs of integers, so you can use `groupby()` to group them. – Sven Marnach Aug 03 '12 at 12:03
  • Wow, this is really cool! I don't think it quite does what the OP wants though. Wouldn't you need to filter those "runs" with only one element for one, and always skip the last of all others (assuming they are still sorted)? – phant0m Aug 03 '12 at 12:11
  • @phant0m: You wouldn't need to filter anything. If you want to treat the first element specially, you can simply use `next(group)` before the loop to access it, and leave the loop as it is. It won't run if `group` consists of only a single element, since this element will have been consumed by `next(group)`. (I don't know what exactly the OP wants to do, because she didn't say.) – Sven Marnach Aug 03 '12 at 12:14
1

This will do what you want.

data=[[a,b,c,1200],[a,g,x,3401],[f,a,c,3402],[f,a,c,3403]etc]
previous = 0 # adjust if necessary
for item in data:
    if item[-1] == previous + 1:
        #do something
    previous = item[-1]

next(item[-1]) does not do what you think. You can deduce this yourself by applying some reasoning:

  1. next(), doesn't receive the actual precursor to the "next" element that you want, that would be item
  2. if you were to pass item, next() would have to figure out what list item is part of.
  3. What if item is in multiple lists? What if it occurs multiple times in the same list? Which item to return?

As you can see, there is no possible way to get the next item in a list by simply passing it some random object that happens to be part of some list.

What next() actually does is quite different. It gives you the next item produced from an iterator/generator.

phant0m
  • 16,595
  • 5
  • 50
  • 82
  • Thanks! However, this still brings up TypeError: Can't convert 'int' object to str implicitly – Snaaa Aug 03 '12 at 12:03
  • @Snaa: Then your `data` is not as displayed in my code. You may need to wrap `item[-1]` with `int()`. – phant0m Aug 03 '12 at 12:04
  • 1
    @Snaaa: Is it possible that not alle last elements in `data` are actually integers? – Sven Marnach Aug 03 '12 at 12:04
  • @Snaaa: I have just noticed that my code will actually run if the previous element is one less than the current. I.e. in `[1, 2, 3]`, it would run for elements `2` and `3`, instead of `1` and `2`. If you want the other behavior, I can modify the code accordingly. – phant0m Aug 03 '12 at 12:18
0

You need to convert your types properly.

if int(next(item[-1])) == int(item[1]) + 1:

Also, i'm not understanding why you don't just do

 if int(item[0]) == int(item[1]) + 1:

Be prepared to catch a ValueError if the conversion fails.

pyrospade
  • 7,870
  • 4
  • 36
  • 52
  • Thanks! I'm trying to compare the last element of a list in a nested list with the last element of the next list in the nested list, hence the next(). Adding int() brings up ValueError: invalid literal for int() with base 10: 'Unique\n' – Snaaa Aug 03 '12 at 11:51