删除2D列表中的连续重复项,python?

时间:2014-03-14 14:10:59

标签: python python-2.7 arraylist nested-lists itertools

如何根据特定元素(在本例中为第2个元素)从2d列表中删除连续重复项。

我尝试了几种与itertools的组合,但没有运气。

有谁能建议我如何解决这个问题?

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

输出


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

这是预期的输出。

更新


以上给出的是列表的精美打印形式。

实际列表如下所示。

>>> 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]

3 个答案:

答案 0 :(得分:3)

因为你想要保留订单并且只是弹出连续的条目,我不知道你可以使用任何花哨的内置。所以,这里的蛮力"方法:

>>> 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]
>>>

或者,如果您想一次性完成所有操作,请使用列表理解:

>>> 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]

答案 1 :(得分:2)

使用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)

打印出来

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

(这使用字符串列表,但很容易适应列表列表。)

答案 2 :(得分:0)

Pandas.groupbyitertools.groupby的替代方法,它还允许您跟踪原始列表的连续/非连续元素---通过给出行号而不是迭代器。像这样:

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

然后,您可以按第二列对它们进行分组,然后将这些组打印为

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]}

查看各行号?在gps的每个列表中有多种方法可以删除连续重复项。这是一个:

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]

最后,将pandas DataFrame索引为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