Python 通过匹配列表中两个子元素的位置对列表中的元组进行分组
我有一个元组列表,如下所示。元组本身是一个嵌套的元组,其中包含3个子元素(元组)Python 通过匹配列表中两个子元素的位置对列表中的元组进行分组,python,list,group-by,grouping,itertools,Python,List,Group By,Grouping,Itertools,我有一个元组列表,如下所示。元组本身是一个嵌套的元组,其中包含3个子元素(元组) [(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')), (('a', 'apple'), ('b', 'mango'), ('c', 'grapes')), (('e', 'apple'), ('b', 'mango'), ('c', 'grapes')), (('a', 'apple'), ('d', 'mango'), ('c', 'peach')), (
[(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('e', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('a', 'apple'), ('d', 'mango'), ('c', 'peach')),
(('e', 'apple'), ('d', 'mango'), ('f', 'grapes')),
(('f', 'grapes'), ('e', 'apple'), ('d', 'mango')),
(('f', 'peach'), ('e', 'apple'), ('e', 'mango')),
(('f', 'grapes'), ('c', 'apple'), ('d', 'mango')),
(('e', 'apple'), ('f', 'grapes'), ('d', 'mango')),
(('a', 'apple'), ('c', 'grapes'), ('b', 'mango')),
]
我想通过匹配两个元组元素的位置来对这些元组进行分组。元组中的苹果和芒果(这是事先确定和已知的)
期望输出:
[
# apple and mango at positions 1 and 2.
[(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('e', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('a', 'apple'), ('d', 'mango'), ('c', 'peach')),
(('e', 'apple'), ('d', 'mango'), ('f', 'grapes'))],
# apple and mango at positions 2 and 3.
[(('f', 'grapes'), ('e', 'apple'), ('d', 'mango')),
(('f', 'peach'), ('e', 'apple'), ('e', 'mango')),
(('f', 'grapes'), ('c', 'apple'), ('d', 'mango'))],
# apple and mango at positions 1 and 3.
[(('e', 'apple'), ('f', 'grapes'), ('d', 'mango')),
(('a', 'apple'), ('c', 'grapes'), ('b', 'mango'))]
]
我尝试使用并检查了一些其他示例,但未能成功接近所需的输出。因此,任何帮助或建议都将不胜感激。我的分组任务解决方案如下。我已经写了一个关于分组的长篇回答,你可以阅读。从答案中找出相关的片段,我们可以得到以下代码:
import collections
groupdict = collections.defaultdict(list)
for value in your_list_of_tuples: # input
group = ??? # group identifier
groupdict[group].append(value)
result = list(groupdict.values()) # output
剩下的就是找到一种方法,用一个可散列值唯一地表示每个组(也就是说,我们需要填写group=?
行)
最简单的解决方案可能是从嵌套元组中提取apple
和mango
值,并用None
替换所有其他值:
>>> tup = (('a', 'apple'), ('c', 'grapes'), ('b', 'mango'))
>>> tuple((t[1] if t[1] in {'apple','mango'} else None) for t in tup)
('apple', None, 'mango')
加上这一点,我们就完成了:
import collections
groupdict = collections.defaultdict(list)
for value in your_list_of_tuples:
group = tuple((t[1] if t[1] in {'apple','mango'} else None) for t in value)
groupdict[group].append(value)
result = list(groupdict.values())
# result:
# [[(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
# (('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
# (('e', 'apple'), ('b', 'mango'), ('c', 'grapes')),
# (('a', 'apple'), ('d', 'mango'), ('c', 'peach')),
# (('e', 'apple'), ('d', 'mango'), ('f', 'grapes'))],
# [(('f', 'grapes'), ('e', 'apple'), ('d', 'mango')),
# (('f', 'peach'), ('e', 'apple'), ('e', 'mango')),
# (('f', 'grapes'), ('c', 'apple'), ('d', 'mango'))],
# [(('e', 'apple'), ('f', 'grapes'), ('d', 'mango')),
# (('a', 'apple'),('c', 'grapes'), ('b', 'mango'))]]
另一种方法是使用每对子项的位置作为键来制作字典 给定的
import more_itertools as mit
iterables = [
(("a", "apple"), ("b", "mango"), ("c", "grapes")),
(("a", "apple"), ("b", "mango"), ("c", "grapes")),
(("e", "apple"), ("b", "mango"), ("c", "grapes")),
(("a", "apple"), ("d", "mango"), ("c", "peach")),
(("e", "apple"), ("d", "mango"), ("f", "grapes")),
(("f", "grapes"), ("e", "apple"), ("d", "mango")),
(("f", "peach"), ("e", "apple"), ("e", "mango")),
(("f", "grapes"), ("c", "apple"), ("d", "mango")),
(("e", "apple"), ("f", "grapes"), ("d", "mango")),
(("a", "apple"), ("c", "grapes"), ("b", "mango")),
]
whitelisted = "apple mango".split()
代码
首先,我们构建了一个索引列表,用于在iterables
中出现的白名单
子项
pred = lambda x: x[1] in set(whitelisted)
indices = [tuple(mit.locate(t, pred=pred)) for t in iterables]
print(indices)
# [(0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (1, 2), (1, 2), (1, 2), (0, 2), (0, 2)]
最后,是使用自定义键和值生成defaultdict
的一种方法
result = mit.map_reduce(zip(indices, iterable), keyfunc=lambda x: x[0], valuefunc=lambda x: x[1])
result
输出
defaultdict(None,
{(0, 1): [(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('a', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('e', 'apple'), ('b', 'mango'), ('c', 'grapes')),
(('a', 'apple'), ('d', 'mango'), ('c', 'peach')),
(('e', 'apple'), ('d', 'mango'), ('f', 'grapes'))],
(1, 2): [(('f', 'grapes'), ('e', 'apple'), ('d', 'mango')),
(('f', 'peach'), ('e', 'apple'), ('e', 'mango')),
(('f', 'grapes'), ('c', 'apple'), ('d', 'mango'))],
(0, 2): [(('e', 'apple'), ('f', 'grapes'), ('d', 'mango')),
(('a', 'apple'), ('c', 'grapes'), ('b', 'mango'))]})
详细信息 对于
iterables
中的每个元组,locate
用于生成属于白名单
项集的项的索引。这些结果足以将项目分组在一起。但是,更容易看到返回的实际项目,因此接下来我们使用map\u reduce
构建一个字典
我们迭代了一组
(索引、可重用项)
对keyfunc
将索引转换为键。同样,valuefunc
将iterables
转换为值。如果有两个元组,apple
和mango像('a','apple'),('m','mango'),('a','apple'),('m','mango'),和('m','mango'),('a','apple'))
一样交换('m','mango'),('a','apple'),,则结果是一个defaultdict
,这两个元组是否应该组合在一起?那么它们应该分为不同的组,因为苹果和芒果在第一个元组中的位置是1和2,在第二个元组中的位置是2和1!非常感谢您对您的方法和解决方案的详细解释。它确实帮助了我,作为一个例子,我强调了这是一个基本的例子,以便任何想要帮助的人都能理解它。但是,您的方法帮助我调整了“else部分”,以便对嵌套元组列表中的其他元组元素进行高级分组,如下例所示!group=tuple((t[1]如果t[1]在{'apple','mango'}中,否则t[0]),表示t在值)最后,为了更大的Python开发人员社区的利益,我重视并感谢您的知识共享能力谢谢!:)这也是解决这个问题的一种有趣的方法,尽管我已经使用了@aran提到的解决方案,因为它使我能够调整其他元组元素以进行高级分组。这很好。只需注意,对最终结果的任何调整都可能通过map\u reduce
的关键字参数来完成,即keyfunc
、valuefunc
和reducefunc.
是的,当然!Map_reduce是另一种选择。:)