[英]Comparing tuple values inside list of lists?
我有一个list
如下:
mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
现在,我想要的是将此列表中的每个元素与所有其他元素进行比较,如果该元素是与之比较的元素的子集,则应将其弹出。 例如, [(1, 1)]
是[(1, 1), (1, 2)]
的子集,那么[(1, 1)]
应该从list
中弹出。 同样, [(1, 1), (1, 2)]
是[(1, 1), (1, 2), (1, 3)]
的子集,那么它也应该被弹出。
在这种情况下,我们得到 output 如下:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
我尝试搜索所有可能的答案,但没有一个针对这种特殊情况。
到目前为止,我已经尝试了以下方法,但用处不大:
for i, e in enumerate(mylist):
mylist[i] = tuple(e)
mylist = list(set(mylist))
您需要从mylist
中删除any
列表,其中列表中的all
元组都存在于mylist
的另一个列表中。 这最容易通过分配给一个新列表来完成:
newlist = []
for i, lst in enumerate(mylist):
if not any(all(t in l for t in lst) for l in mylist[:i] + mylist[i+1:]):
newlist.append(lst)
或作为列表理解:
newlist = [lst for i, lst in enumerate(mylist) if not any(all(t in l for t in lst) for l in mylist[:i] + mylist[i+1:])]
在这两种情况下,对于您的示例数据,output 是:
[
[(1, 1), (1, 2), (1, 3)],
[(1, 1), (1, 2), (1, 4)]
]
对于较大的列表,这可能会变慢,在这种情况下,您可以通过首先将mylist
中的条目映射到集合来加快速度:
mylist=[[(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)], [(1, 1)]]
mylist=list(map(set, (tuple(l) for l in mylist)))
newlist = [list(lst) for i, lst in enumerate(mylist) if not any(lst.issubset(l) for l in mylist[:i] + mylist[i+1:])]
您可以使用frozenset.issubset
并像以下示例一样进行比较:
感谢@Nick 的建议,这是一个更详细的示例:
mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1),
(1, 2), (1, 4)]]
out = []
for k, elm in enumerate(mylist):
for elm2 in mylist[:k] + mylist[k + 1:]:
if frozenset(elm).issubset(elm2):
break
else:
out.append(elm)
print(out)
Output:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
@Nick 和 @ChihebNexus 的解决方案都没有效率。
@Nick 的答案需要O(m ^ 2 xn ^ 2)的时间复杂度,而@ChihebNexus 的答案需要O(m ^ 2 xn)的时间复杂度,其中m是输入列表的长度, n是子列表的平均长度。
对于只需要O(mxn)时间复杂度的方法,您可以创建一个 dict 将每个元组项目映射到该项目出现的一组子列表,请记住这些子列表需要转换元组首先变为可散列并添加到集合中:
mapping = {}
for lst in mylist:
for item in lst:
mapping.setdefault(item, set()).add(tuple(lst))
因此,使用您的示例输入, mapping
变为:
{(1, 1): {((1, 1),),
((1, 1), (1, 2)),
((1, 1), (1, 2), (1, 3)),
((1, 1), (1, 2), (1, 4))},
(1, 2): {((1, 1), (1, 2), (1, 3)), ((1, 1), (1, 2)), ((1, 1), (1, 2), (1, 4))},
(1, 3): {((1, 1), (1, 2), (1, 3))},
(1, 4): {((1, 1), (1, 2), (1, 4))}}
然后通过建立项目与其所属子列表的映射,我们可以再次遍历子列表,并取当前子列表 map 中的项目到的子列表集合的交集,在为了找到包含当前子列表中所有项目的子列表。 如果有多个这样的符合条件的子列表,则意味着当前子列表是其他符合条件的子列表的子集,我们可以通过将当前子列表从结果中删除将其项目 map 设置为。 在这个过程中幸存下来的子列表将是我们想要的 output 中的子列表,我们可以通过使用联合操作聚合集合来获得:
for lst in mylist:
if len(set.intersection(*map(mapping.get, lst))) > 1:
t = tuple(lst)
for item in lst:
mapping[item].remove(t)
print(set.union(*mapping.values()))
这输出:
{((1, 1), (1, 2), (1, 3)), ((1, 1), (1, 2), (1, 4))}
如果您真的想要问题中的确切数据类型,可以将其转换为列表列表:
list(map(list, set.union(*mapping.values())))
返回:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.