从列表中删除两个相邻的元组

时间:2018-01-05 19:30:07

标签: python list

鉴于此清单:

[(1, 's'), (2, 'e'), (2, 's'), (3, 'e')]

这是可能重叠的间隔的表示,例如1 --> 22 --> 3,我已将其纳入此表示形式以便于处理(有关上下文,请参阅this answer

我想删除对(2, 'e') - (2, 's'),因为一个时间间隔的结尾(e)是相同的数字(2 )作为下一个区间的开始(s)。所以结果应该是

[(1, 's'), (3, 'e')]

并代表1 --> 3

修改:区间也可能重叠,例如1-->42-->3。这将在此元组列表中表示(请注意,列表已经排序):[(1, 's'), (2, 's'), (3, 'e'), (4, 'e')]。在这种情况下,没有什么需要做,因为没有两个元组共享相同的数字。

我想出了这个减少:

import functools
functools.reduce(lambda l,i: l[:-1] if i[0] == l[-1][0] and i[1] != l[-1][1] else l + [i], a[1:], [a[0]])

有没有更好的方法来实现这一目标?

4 个答案:

答案 0 :(得分:1)

您可以使用itertools.groupby稍长一些(两行),但解决方案更易读:

import itertools
def get_combinations(s):
   new_data = [(a, list(b)) for a, b in itertools.groupby(s, key=lambda x:x[0])]
   return [b[-1] for i, [a, b] in enumerate(new_data) if len(b) == 1 or len(b) > 1 and i == len(new_data) - 1]

print(get_combinations([(1, 's'), (2, 'e'), (2, 's'), (2, 'e')]))
print(get_combinations([(1, 's'), (2, 'e'), (2, 's'), (3, 'e')]))

输出:

[(1, 's'), (2, 'e')]
[(1, 's'), (3, 'e')]

答案 1 :(得分:0)

我最近一直在玩弄功能语言,所以这可能比一些人读得更少Pythonic,但我会使用(修改的)itertools pairwise配方来成对迭代

def pairwise(iterable):
    a, b = itertools.tee(iterable)
    next(b, None)  # advance the second iterator
    return itertools.zip_longest(a, b, fillvalue=(None, None))

然后过滤哪些对彼此不匹配:

def my_filter(a, b):
    a_idx, a_type = a
    b_idx, b_type = b
    if a_idx == b_idx and a_type == "e" and b_type == "s":
        return False
    return True

自己过滤(因为天真的filter会允许“开始”值生效,因为它与前面的元素配对)

def filter_them(some_list):
    pairs = pairwise(some_list)
    acc = []
    while True:
        try:
            a, b = next(pairs)
            if my_filter(a, b):
                acc.append(a)
            else:
                next(pairs)  # skip the next pair
        except StopIteration:
            break
    return acc

答案 2 :(得分:0)

我正在修补一个"双继续"方法,并提出了这个生成器解决方案:

def remove_adjacent(l):
    iterator = enumerate(l[:-1])
    for i, el in iterator:
        if el[0] == l[i+1][0] and el[1] != l[i+1][1]:
            next(iterator)
            continue
        yield el
    yield l[-1]

答案 3 :(得分:-1)

只需将2个临时变量1循环并使用if检查即可轻松完成。