tags:

views:

111

answers:

5

c1 is a list of lists like this:

c1=[[1,2,3],[1,2,6],[7,8,6]]

for row in c1:

i want to keep track of whether there is a change in row[0]

for example:

in [1, 2, 3] and [1, 2, 6] there is no change in row[0]

however in [1, 2, 6] and [ 7, 8, 6] there is a change in row[0]

how do i catch this change? also i would like to know which row this changed occurred at

+2  A: 

Use a variable to keep track of the previous item.

prev = None
for row in c1:
  if prev is not None and prev != row[0]:
     # there is a change
  prev = row[0]

...just make sure you use a nonexistent value as the starting value (if your lists may contain anything, use an extra flag for the first item). If you want the first row to be considered a change, change the if to:

if prev is None or prev != row[0]:
Matti Virkkunen
@Matti, a safe way to set `prev` eg, if there were a possibility of `None` being the first element of the first row is to use `prev = object()`
gnibbler
+2  A: 
>>> from operator import itemgetter
>>> from itertools import groupby
>>> c1=[[1,2,3],[1,2,6],[7,8,6]]
>>> list(groupby(c1,itemgetter(0)))
[(1, <itertools._grouper object at 0xa6f8d0>), (7, <itertools._grouper object at 0xa6f890>)]

this is simply saying group the elements of c1 by the first item of each element

You can also expand the result as a nested list to see how the items are grouped

>>> [(x,list(y)) for x,y in (groupby(c1,itemgetter(0)))]
[(1, [[1, 2, 3], [1, 2, 6]]), (7, [[7, 8, 6]])]

to get the row of the change, you can look at the length of the first element of the result

>>> len(list(next(groupby(c1,itemgetter(0)))[1]))
2
gnibbler
wowow! can you please explain the last two lines
I__
That was also the direction in which I was thinking. Though I was thinking not of groupby but of putting the elements in a Set (or a multiset to keep the count).
extraneon
how do i get the last line to give me the ROW where the change occurred instead of the address
I__
@l__ the itemgetter takes the first element of every input. The groupby iterates and thus itemgetter takes the first elelement of [1,2,3], the first of [1,2,6], and so forth.
extraneon
@l__ you are actually adding a requirement. You wanted to know IF, and not WHERE, the change occurred.
extraneon
yes you are right i am adding a requirement
I__
@l__Then add it to the requirements (the question).
extraneon
gnibbler thank you very much. im a python beginner and this functionality is very interesting for me; however, i decided to use the other answer because i can get my head around it easier
I__
@extraneon, `set(x[0] for x in c1)` is a simple way of detecting that there is a change. I must have anticipated that extra requirement :)
gnibbler
@gnibbler I like your set thing. I'd upvote it in a sec if it were an answer!
extraneon
+1  A: 

I've posted this as a separate answer to avoid making the other answer too jumbled

>>> for i in range(1,len(c1)):
...  if c1[i-1][0]!=c[i][0]: break
...
>>> print i
2
gnibbler
+1  A: 

If you had matrix data you basically want a diff of the first "column". You probably want to report the changes and the location of the changes and probably want to store them sparsely:

c1=[[1,2,3],[1,2,6],[7,8,6]]
ans=[]    # a list of [indices,differences]
col=0
for i in range(len(c1)-1):
    diff = c1[i+1][col]-c1[i][col]
    if diff!=0:
        ans.append([i,diff])
mathtick
+1  A: 

Print a list of all rows with a different first element than its predecessor:

import itertools

c1=[[1,2,3],[1,2,6],[7,8,6]]

xs, ys = itertools.tee(c1)
next(ys)
print [y for x, y in itertools.izip(xs, ys) if x[0] != y[0]]
pillmuncher