简体   繁体   English

如何根据谓词拆分Python元组序列?

[英]How to split a Python sequence of tuples according to a predicate?

I have a sequence of tuples such as: 我有一个元组序列,例如:

[(0.0, 0.25), (0.25, 0.25), (0.5, 0.5), (1.0, 0.25), (1.25, 0.75), (2.0, 1.0)]

I'd like to split this sequence in such way that the first element of the first tuple of the split sequence is an integer: 我想以这种方式拆分该序列,以使拆分序列的第一个元组的第一个元素是整数:

[[(0.0, 0.25), (0.25, 0.25), (0.5, 0.5)],
 [(1.0, 0.25), (1.25, 0.75)],
 [(2.0, 1.0)]]

I tried to write something with filter(sequence, lambda x: x[0].is_integer()) , but I only got the first tuples of the split sequence. 我试图用filter(sequence, lambda x: x[0].is_integer()) ,但是我只得到了分割序列的第一个元组。 How can I do this? 我怎样才能做到这一点?

Does this work as you want? 这可以按您的意愿工作吗?

>>> testList = [(0.0, 0.25), (0.25, 0.25), (0.5, 0.5), (1.0, 0.25), (1.25, 0.75), (2.0, 1.0)]
>>> from operator import itemgetter
>>> testList.sort(key=itemgetter(0)) # Making sure it is sorted. If list is pre-sorted, skip this step.
>>> from itertools import groupby
>>> final_list = [list(lst) for _, lst in groupby(testList, lambda x: int(x[0]))]
>>> from pprint import pprint
>>> pprint(final_list)
[[(0.0, 0.25), (0.25, 0.25), (0.5, 0.5)],
 [(1.0, 0.25), (1.25, 0.75)],
 [(2.0, 1.0)]]

For any simpletons like me ;) 对于像我这样的简单人物;)

a = [(0.0, 0.25), (0.25, 0.25), (0.5, 0.5), (1.0, 0.25), (1.25, 0.75), (2.0, 1.0)]
key, value = zip(*a)

index = 0
output = []
index_dict = {}
for i in range(0, len(key)):
    k, v = key[i], value[i]
    if int(k) in index_dict:
            output[index_dict[int(k)]].append((k, v))
    else:
            index_dict[int(k)] = index
            output.append([(k, v)])
            index += 1

I assume that the first element of the first tuple is an integer. 我假设第一个元组的第一个元素是整数。

You can use the reduce() function to solve it in one line and single pass over the list: 您可以使用reduce()函数在列表中一行并单遍解决它:

>>> l = [(0.0, 0.25), (0.25, 0.25), (0.5, 0.5), (1.0, 0.25), (1.25, 0.75), (2.0, 1.0)]
>>> reduce(lambda acc, x: acc + [[x]] if x[0].is_integer() else acc[:-1] + [acc[-1] + [x]], l, [])
[[(0.0, 0.25), (0.25, 0.25), (0.5, 0.5)], 
[(1.0, 0.25), (1.25, 0.75)], 
[(2.0, 1.0)]]

This is pretty straight forward and not that beautiful, but works: 这是很直接的,不是那么漂亮,但是可以:

from itertools import takewhile
from pprint import pprint


l = [(0.0, 0.25), (0.25, 0.25), (0.5, 0.5), (1.0, 0.25), (1.25, 0.75), (2.0, 1.0)]

result = []
i = 0
while i < len(l):
    item = [l[i]] + list(takewhile(lambda x: x[0] % 1, l[i + 1:]))
    result.append(item)
    i += len(item)

pprint(result)

prints: 打印:

[[(0.0, 0.25), (0.25, 0.25), (0.5, 0.5)],
 [(1.0, 0.25), (1.25, 0.75)],
 [(2.0, 1.0)]]

Using collections.defaultdict , you can easily do this without loss of redability 使用collections.defaultdict ,您可以轻松地做到这一点而不会损失可重复性

>>> from collections import defaultdict
>>> some_list = [(0.0, 0.25), (0.25, 0.25), (0.5, 0.5), (1.0, 0.25), (1.25, 0.75), (2.0, 1.0)]
>>> accum = defaultdict(list)
>>> for e in some_list:
    accum[int(e[0])].append(e)


>>> import pprint
>>> pp = pprint.PrettyPrinter(indent=4)
>>> pp.pprint(accum.values())
[   [(0.0, 0.25), (0.25, 0.25), (0.5, 0.5)],
    [(1.0, 0.25), (1.25, 0.75)],
    [(2.0, 1.0)]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM