Question

How can i remove consecutive duplicates from a 2d list according to a particular element ( in this case the 2nd element) .

i tried few combinations with itertools but had no luck .

Can anyone suggest me how to solve this ?

INPUT


192.168.1.232  >>>>>   173.194.36.64 , 14 , 15 , 16
192.168.1.232  >>>>>   173.194.36.64 , 14 , 15 , 17
192.168.1.232  >>>>>   173.194.36.119 , 23 , 30 , 31
192.168.1.232  >>>>>   173.194.36.98 , 24 , 40 , 41
192.168.1.232  >>>>>   173.194.36.98 , 24 , 40 , 62
192.168.1.232  >>>>>   173.194.36.74 , 25 , 42 , 43
192.168.1.232  >>>>>   173.194.36.74 , 25 , 42 , 65
192.168.1.232  >>>>>   173.194.36.74 , 26 , 44 , 45
192.168.1.232  >>>>>   173.194.36.74 , 26 , 44 , 66
192.168.1.232  >>>>>   173.194.36.78 , 27 , 46 , 47

OUTPUT


192.168.1.232  >>>>>   173.194.36.64 , 14 , 15 , 16
192.168.1.232  >>>>>   173.194.36.119 , 23 , 30 , 31
192.168.1.232  >>>>>   173.194.36.98 , 24 , 40 , 41
192.168.1.232  >>>>>   173.194.36.74 , 25 , 42 , 43
192.168.1.232  >>>>>   173.194.36.78 , 27 , 46 , 47

This the expected output.

UPDATE


The above given is a nicely printed form of the list.

the actual list looks like this .

>>> for x  in connection_frame:
    print x


['192.168.1.232', '173.194.36.64', 14, 15, 16]
['192.168.1.232', '173.194.36.64', 14, 15, 17]
['192.168.1.232', '173.194.36.119', 23, 30, 31]
['192.168.1.232', '173.194.36.98', 24, 40, 41]
['192.168.1.232', '173.194.36.98', 24, 40, 62]
['192.168.1.232', '173.194.36.74', 25, 42, 43]
['192.168.1.232', '173.194.36.74', 25, 42, 65]
['192.168.1.232', '173.194.36.74', 26, 44, 45]
['192.168.1.232', '173.194.36.74', 26, 44, 66]
['192.168.1.232', '173.194.36.78', 27, 46, 47]
['192.168.1.232', '173.194.36.78', 27, 46, 67]
['192.168.1.232', '173.194.36.78', 28, 48, 49]
['192.168.1.232', '173.194.36.78', 28, 48, 68]
['192.168.1.232', '173.194.36.79', 29, 50, 51]
['192.168.1.232', '173.194.36.79', 29, 50, 69]
['192.168.1.232', '173.194.36.119', 32, 52, 53]
['192.168.1.232', '173.194.36.119', 32, 52, 74]
Was it helpful?

Solution

So because you want to preserve order and only pop connsecutive entries, I don't know of any fancy built-in you can use. So here's the "brute-force" method:

>>> remList = []
>>> for i in range(len(connection_frame)):
...     if (i != len(connection_frame)-)1 and (connection_frame[i][1] == connection_frame[i+1][1]):
...         remList.append(i)
...
for i in remList:
    connection_frame.pop(i)
['192.168.1.232', '173.194.36.119', 32, 52, 53]
['192.168.1.232', '173.194.36.79', 29, 50, 51]
['192.168.1.232', '173.194.36.78', 28, 48, 49]
['192.168.1.232', '173.194.36.78', 27, 46, 67]
['192.168.1.232', '173.194.36.78', 27, 46, 47]
['192.168.1.232', '173.194.36.74', 26, 44, 45]
['192.168.1.232', '173.194.36.74', 25, 42, 65]
['192.168.1.232', '173.194.36.74', 25, 42, 43]
['192.168.1.232', '173.194.36.98', 24, 40, 41]
['192.168.1.232', '173.194.36.64', 14, 15, 16]
>>>
>>> for conn in connection_frame:
...     print conn
...
['192.168.1.232', '173.194.36.64', 14, 15, 17]
['192.168.1.232', '173.194.36.119', 23, 30, 31]
['192.168.1.232', '173.194.36.98', 24, 40, 62]
['192.168.1.232', '173.194.36.74', 26, 44, 66]
['192.168.1.232', '173.194.36.78', 28, 48, 68]
['192.168.1.232', '173.194.36.79', 29, 50, 69]
['192.168.1.232', '173.194.36.119', 32, 52, 74]
>>>

Or if you wanna do it all in one go with a list comprehension:

>>> new_frame = [conn for conn in connection_frame if not connection_frame.index(conn) in [i for i in range(len(connection_frame)) if (i != len(connection_frame)-1) and (connection_frame[i][1] == connection_frame[i+1][1])]]
>>>
>>> for conn in new_frame:
...     print conn
...
['192.168.1.232', '173.194.36.64', 14, 15, 17]
['192.168.1.232', '173.194.36.119', 23, 30, 31]
['192.168.1.232', '173.194.36.98', 24, 40, 62]
['192.168.1.232', '173.194.36.74', 26, 44, 66]
['192.168.1.232', '173.194.36.78', 28, 48, 68]
['192.168.1.232', '173.194.36.79', 29, 50, 69]
['192.168.1.232', '173.194.36.119', 32, 52, 74]

OTHER TIPS

Use itertools.groupby():

import itertools

data = """192.168.1.232  >>>>>   173.194.36.64 , 14 , 15 , 16
192.168.1.232  >>>>>   173.194.36.64 , 14 , 15 , 17
192.168.1.232  >>>>>   173.194.36.119 , 23 , 30 , 31
192.168.1.232  >>>>>   173.194.36.98 , 24 , 40 , 41
192.168.1.232  >>>>>   173.194.36.98 , 24 , 40 , 62
192.168.1.232  >>>>>   173.194.36.74 , 25 , 42 , 43
192.168.1.232  >>>>>   173.194.36.74 , 25 , 42 , 65
192.168.1.232  >>>>>   173.194.36.74 , 26 , 44 , 45
192.168.1.232  >>>>>   173.194.36.74 , 26 , 44 , 66
192.168.1.232  >>>>>   173.194.36.78 , 27 , 46 , 47""".split("\n")

for k, g in itertools.groupby(data, lambda l:l.split()[2]):
  print next(g)

This prints out

192.168.1.232  >>>>>   173.194.36.64 , 14 , 15 , 16
192.168.1.232  >>>>>   173.194.36.119 , 23 , 30 , 31
192.168.1.232  >>>>>   173.194.36.98 , 24 , 40 , 41
192.168.1.232  >>>>>   173.194.36.74 , 25 , 42 , 43
192.168.1.232  >>>>>   173.194.36.78 , 27 , 46 , 47

(This uses a list of strings but is trivial to adapt to a list of lists.)

Pandas.groupby is an alternative to itertools.groupby that also allows you to keep track of consecutive/non-consecutive elements of the original list --- by giving row numbers instead of iterator. Something like this:

df = pandas.DataFrame(connection_frame)
print df
Out:
                0                  1    2    3    4
0   '192.168.1.232'    '173.194.36.64'   14   15   16
1   '192.168.1.232'    '173.194.36.64'   14   15   17
2   '192.168.1.232'   '173.194.36.119'   23   30   31
3   '192.168.1.232'    '173.194.36.98'   24   40   41
4   '192.168.1.232'    '173.194.36.98'   24   40   62
5   '192.168.1.232'    '173.194.36.74'   25   42   43
6   '192.168.1.232'    '173.194.36.74'   25   42   65
7   '192.168.1.232'    '173.194.36.74'   26   44   45
8   '192.168.1.232'    '173.194.36.74'   26   44   66
9   '192.168.1.232'    '173.194.36.78'   27   46   47
10  '192.168.1.232'    '173.194.36.78'   27   46   67
11  '192.168.1.232'    '173.194.36.78'   28   48   49
12  '192.168.1.232'    '173.194.36.78'   28   48   68
13  '192.168.1.232'    '173.194.36.79'   29   50   51
14  '192.168.1.232'    '173.194.36.79'   29   50   69
15  '192.168.1.232'   '173.194.36.119'   32   52   53
16  '192.168.1.232'   '173.194.36.119'   32   52   74

Then, you can group them by 2nd column and print the groups as

gps = df.groupby(2).groups
print gps
Out: 
{' 14': [0, 1],
 ' 23': [2],
 ' 24': [3, 4],
 ' 25': [5, 6],
 ' 26': [7, 8],
 ' 27': [9, 10],
 ' 28': [11, 12],
 ' 29': [13, 14],
 ' 32': [15, 16]}

See the individual row numbers? There are many ways of removing consecutive duplicates in each list of gps. Here is one:

valid_rows = list()
for g in gps.values():
   old_row = g[0]
   valid_rows.append(old_row)
   for row_id in range(1, len(g)):
      new_row = g[row_id]
      if new_row - old_row != 1:
         valid_rows.append(new_row)
      old_row = new_row
 print valid_rows
 Out: [5, 3, 9, 7, 0, 2, 15, 13, 11]

Finally, index the pandas DataFrame by valid_rows.

print df.ix[sorted(valid_rows)]
Out:


0   '192.168.1.232'    '173.194.36.64'   14   15   16
2   '192.168.1.232'   '173.194.36.119'   23   30   31
3   '192.168.1.232'    '173.194.36.98'   24   40   41
5   '192.168.1.232'    '173.194.36.74'   25   42   43
7   '192.168.1.232'    '173.194.36.74'   26   44   45
9   '192.168.1.232'    '173.194.36.78'   27   46   47
11  '192.168.1.232'    '173.194.36.78'   28   48   49
13  '192.168.1.232'    '173.194.36.79'   29   50   51
15  '192.168.1.232'   '173.194.36.119'   32   52   53
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top