鉴于此清单:
[(1, 's'), (2, 'e'), (2, 's'), (3, 'e')]
这是可能重叠的间隔的表示,例如1 --> 2
和2 --> 3
,我已将其纳入此表示形式以便于处理(有关上下文,请参阅this answer)
我想删除对(2, 'e')
- (2, 's')
,因为一个时间间隔的结尾(e
)是相同的数字(2
)作为下一个区间的开始(s
)。所以结果应该是
[(1, 's'), (3, 'e')]
并代表1 --> 3
。
修改:区间也可能重叠,例如1-->4
和2-->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]])
有没有更好的方法来实现这一目标?
答案 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检查即可轻松完成。