使用Python比较和丢弃两个不符合列表中某些条件的连续元素

时间:2014-02-28 10:49:48

标签: python arrays compare elements

所以我在Python中有这个列表,我在下面展示,为了简单起见,我将它命名为p

 [[11 10]
  [12  9]
  [13  9]
  [13 10]
  [14  8]
  [14 10]
  [15  7]
  [15  9]
  [16  8]
  [17  7]
  [18  2]
  [18  8]
  [19  1]
  [19  7]
  [20  1]
  [20  2]
  [21  2]
  [21  4]
  [22  1]
  [22  3]
  [23  4]
  [24  3]
  [25  4]
  [25  6]
  [26  3]
  [26  5]
  [27  5]
  [27  6]
  [28  8]
  [28 10]
  [29  6]
  [30  5]
  [31  7]
  [31  9]
  [32  1]
  [32  2]
  [33  4]
  [33  6]
  [34  3]
  [34  5]] 

我要做的是比较连续的对,然后只让具有相同p[0]的元素。从这个意义上讲,人们可以注意到p[0]= 11,12,16,17,23,24,29,30的对将无法生存,然后p将成为:

[[13  9]
 [13 10]
 [14  8]
 [14 10]
 [15  7]
 [15  9]
 [18  2]
 [18  8]
 [19  1]
 [19  7]
 [20  1]
 [20  2]
 [21  2]
 [21  4]
 [22  1]
 [22  3]
 [25  4]
 [25  6]
 [26  3]
 [26  5]
 [27  5]
 [27  6]
 [28  8]
 [28 10]
 [31  7]
 [31  9]
 [32  1]
 [32  2]
 [33  4]
 [33  6]
 [34  3]
 [34  5]] 

在python中这样做的方法是什么?如果有人能给我一个想法,我会很高兴的。

4 个答案:

答案 0 :(得分:0)

假设输入列表被命名为lst,并且你想要使用孤独的第一个元素全局来杀死项目,你可以这样做:

from collections import Counter
cnt = Counter(zip(*lst)[0])
result = [p for p in lst if cnt[p[0]] > 1]
print result

输出:

[[13, 9], [13, 10], [14, 8], [14, 10], [15, 7], [15, 9], [18, 2], [18, 8], [19, 1], [19, 7], [20, 1], [20, 2], [21, 2], [21, 4], [22, 1], [22, 3], [25, 4], [25, 6], [26, 3], [26, 5], [27, 5], [27, 6], [28, 8], [28, 10], [31, 7], [31, 9], [32, 1], [32, 2], [33, 4], [33, 6], [34, 3], [34, 5]]

但上面的代码确实不正确 - 我忽略了问题对连续性的要求。为了完整起见,让我写出所谓正确的解决方案:

from itertools import groupby
from operator import itemgetter
result = []
for _, k in groupby(lst, itemgetter(0)):
    k = list(k)
    if len(k) > 1:
        result.extend(k)
print result

尽管如此,它们应该为这个特定的例子产生相同的结果。您应该使用更复杂的输入进行测试,例如

[[11,0],[11,0],[12,0],[13,0],[12,0],[13,0]]

并且唯一的第二个解决方案将根据您的要求给出正确答案。

答案 1 :(得分:0)

请注意,原始问题是“比较连续对,然后只允许具有相同p [0]的元素”,这意味着不应该对原始列表进行排序。如果对原始列表进行排序,那么将拾取并保留原本不是“连续”的对。虽然样本列表已经排序,但我不会认为是这样的,所以这也将处理一个案例,如

[[13, 5],
 [13, 2],
 [14, 9],
 [13. 6]]

生成

[[13, 5],
 [13, 2]]

我将展示一个简单的循环,以便更容易理解,但列表理解可以缩短它。请注意,Counter需要python 2.7

prev = None
newp = []
length = len(p) - 1
for i in range(length):
  if p[i][0] == p[i+1][0] or p[i][0] == prev:
    newp.append(p[i])
    prev = p[i][0]

if p[length][0] == p[length-1][0]:
  newp.append(p[length])

这将根据需要创建新列表

答案 2 :(得分:0)

编写生成器使其具有可读性(您可以为自己的名字命名):

def find_pairs(items):
    last = (None, None)
    for item in items:
        if item[0] == last[0]:
            yield last
            yield item
        last = item

print [x for x in find_pairs(p)]

答案 3 :(得分:0)

使用列表理解的可能解决方案:

  1. 想法是向前看和向后看并选择是否匹配。要避免IndexError边界情况,请使用i > 0i < len(A)-1

    >>> ans = [el for i, el in enumerate(A) if (i > 0 and A[i-1][0] == el[0]) or \
    (i < len(A)-1 and A[i+1][0] == el[0])]

  2. 预先添加和附加虚拟值以避免处理IndexError

    >>> A = [[None, None]] + A + [[None, None]]
    >>> ans = [el for i, el in enumerate(A) if A[i-1][0] == el[0] or \
    A[i+1][0] == el[0]] 
    

  3. 使用zip获取下一个和上一个元素

    >>> A = [[None, None]] + A + [[None, None]]
    >>> ans = [e2 for e1, e2, e3 in zip(A, A[1:], A[2:]) if e2[0] == e1[0] or \
    e2[0] == e3[0]]