[英]Elegant way to extract a tuple from list of tuples with minimum value of element
[英]What's an elegant way to extract a series of entries in a list of tuples into sublists?
假設我在這樣的元組列表中有一系列條目:
TRUE = 1
listOfTuples = [('selectable', 'frequency'), ('color', 'green'), ('item', '10 Hz'),
('value', 10), ('align', 'left'), ('hidden', TRUE), ('item', '20 Hz'),
('value', 20), ('align', 'right'), ('item', '50 Hz'), ('value', 50),
('item', '100 Hz'), ('value', 100), ('textColor', 0xFF0000)]
現在我想提取一個包含單個項目條目的列表,如下所示:
[(('item', '10 Hz'), ('value', 10), ('align', 'left'), ('hidden', TRUE)),
(('item', '20 Hz'), ('value', 20), ('align', 'right')),
(('item', '50 Hz'), ('value', 50)),
(('item', '100 Hz'), ('value', 100), ('textColor', '0xFF0000'))]
標識子列表的定界關鍵字始終是item
或列表末尾。 兩個相鄰的分隔符之間可以有任意數量的元組。 item
第一次出現之前的列表內容將被忽略。 關鍵字item
的檢測應該不區分大小寫。
我不是 Python 愛好者,所以我不知道如何應用列表理解之類的東西(如果這真的可能的話),因為我需要在定界符之間提取列表。 當然,我可以通過遍歷列表、識別關鍵字在元組中的位置然后提取子列表來以行人方式完成,但我希望有一個更優雅的解決方案。
您可以使用itertools.groupby
來完成任務:
from itertools import accumulate, groupby
TRUE = 1
listOfTuples = [
("selectable", "frequency"),
("color", "green"),
("item", "10 Hz"),
("value", 10),
("align", "left"),
("hidden", TRUE),
("item", "20 Hz"),
("value", 20),
("align", "right"),
("item", "50 Hz"),
("value", 50),
("item", "100 Hz"),
("value", 100),
("textColor", 0xFF0000),
]
a = accumulate(t == "item" for t, *_ in listOfTuples)
out = []
for _, g in groupby(zip(a, listOfTuples), lambda k: k[0]):
l = tuple(t for _, t in g)
if l[0][0] == "item":
out.append(l)
print(out)
印刷:
[
(("item", "10 Hz"), ("value", 10), ("align", "left"), ("hidden", 1)),
(("item", "20 Hz"), ("value", 20), ("align", "right")),
(("item", "50 Hz"), ("value", 50)),
(("item", "100 Hz"), ("value", 100), ("textColor", 16711680)),
]
您可以使用tuple()
function 將列表轉換為元組,這樣您就可以將 append listOfTuples
變量中的所有元組轉換為您需要的 output:
TRUE = 1
lot = [('selectable', 'frequency'), ('color', 'green'), ('item', '10 Hz'),
('value', 10), ('align', 'left'), ('hidden', TRUE), ('item', '20 Hz'),
('value', 20), ('align', 'right'), ('item', '50 Hz'), ('value', 50),
('item', '100 Hz'), ('value', 100), ('textColor', 0xFF0000)]
l = [[]]
for i in lot:
if i[0]=='item':
l[-1] = tuple(l[-1])
l.append([])
l[-1].append(i)
print(l[1:])
Output:
[(('item', '10 Hz'), ('value', 10), ('align', 'left'), ('hidden', 1)), (('item', '20 Hz'), ('value', 20), ('align', 'right')), (('item', '50 Hz'), ('value', 50)), [('item', '100 Hz'), ('value', 100), ('textColor', 16711680)]]
這種方法唯一的缺點是需要刪除 output 元組列表的第一個元素,因此在某些情況下它可能不起作用。
好的,所以與此同時,我了解了更多關於列表理解、 _
、 *
和 for 循環中多個索引的使用。 此外,一位好朋友提出了以下解決方案:
indices = [i for i, value in enumerate(listOfTuples)
if value[0].casefold() == "item"] + [len(listOfTuples)]
out = [listOfTuples[i:j] for i,j in zip(indices[:-1], indices[1:])]
Indices
包含所有出現的item
和列表中最后一項的索引。 以移位的方式使用indices
( zip(indices[:-1], indices[1:])
) 允許直接構建out
。
一種沒有條件的建設性方法。 使用itertools.groupby
按'item'
分組。 分組是一個 True/False 分類過程(理想情況下會引發 True/False 值的交替序列! ),因此您可以按 2 個塊進行切片並將它們鏈接在一起。
右拆分( initial )條件意味着在“右邊”找到第一個帶有item
的組,並且可以忘記“左邊”的內容( [1:]
-部分)。
import itertools as it
listOfTuples = # see question
# group by item & discard 1st group due to split-right condition
lst = tuple(tuple(grps) for _, grps in it.groupby(listOfTuples, lambda p: p[0] == 'item'))[1:]
# chain the slices
lst_new = [tuple(it.chain.from_iterable(lst[2*i:2*(i+1)])) for i in range(len(lst)//2)]
print(lst_new)
相同的想法,但有發電機
...
lst = (tuple(grps) for _, grps in it.groupby(listOfTuples, lambda p: p[0] == 'item'))
next(l) # split-right initial condition
l1, l2 = it.tee(lst)
n = len(tuple(l2))
lst_new = [tuple(it.chain.from_iterable(it.islice(l1, 0, 2, None))) for _ in range(n//2)]
一種(邏輯上不同的)基於索引的方法
...
# indices of the items
iter_ = filter(None, (tuple(grps)[0][0] if check else None for check, grps in it.groupby(enumerate(listOfTuples), lambda p: p[1][0] == 'item')))
# zip-stuffs
it1, it2 = it.tee(iter_)
next(it2)
it2 = it.chain(it2, iter((len(listOfTuples),)))
# apply the slices and cast to tuples
lst_new = list(map(tuple, map(listOfTuples.__getitem__, it.starmap(slice, zip(it1, it2)))))
print(lst_new)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.