【问题标题】:How to check if a slice of a tuple in a set of tuples is in another set of tuples?如何检查一组元组中的一个元组切片是否在另一组元组中?
【发布时间】:2021-02-19 14:24:18
【问题描述】:

假设:我有两组元组,而且任何一组都可能不包含相同数量的元组。 有什么方法可以在不迭代两组并将一组中的每个条目与另一组的每个条目进行比较的情况下使其工作?

例如,我想知道一个元组的三个条目是否在另一组的任何元组中,这是我尝试过的(示例代码):

s1 = set()
s2 = set()
s1.add(tuple(["a", "b", "c", "e"]))
s1.add(tuple(["d", "e", "f", "h"]))
s2.add(tuple(["a", "b", "c", "d"]))
s2.add(tuple(["d", "e", "f", "g"]))
s2.add(tuple(["m", "n", "o", "p"]))

for x in s1:
    if x[0:3] in s2:
        print(x)

这行不通。

我之所以问,是因为这些集合有数千个条目,并且对两者都进行了迭代 花费的时间太长了,我似乎想不出一个聪明的方法来做到这一点。

编辑澄清: 每个元组总是有相同数量的条目,在我的例子中是 4。 就我而言,我想知道如何检查任意组合 [0:2]、[1:3]、[0:x]。例如,我需要确认一个元组中的 [0:3] 与另一个元组中的 [0:3] 相同。

【问题讨论】:

  • 您的问题需要更清楚。为什么只有 x[0:3]?根据您的示例,您还应该检查 x[1:4] 。如果您不知道元组的长度,则应检查元组中的每 3 个项目子集。您是想检查 set2 中是否存在特定元组,还是只想确认 s2 中存在一个元组,其中包含来自 s1 的 3 个元素的切片?
  • 注意tuple(["a", "b", "c", "e"])可以写成("a", "b", "c", "e")。不需要使用列表作为初始化器。
  • “我之所以问,是因为这些集合有数千个条目,并且迭代这两个条目需要的时间太长,而且我似乎无法找到一个聪明的方法来做到这一点。” – 可能需要一个专门的数据结构,例如suffix tree。如果字母表很小(4 个条目和较低的部分看起来不像常规单词),则可能只创建一个索引。但是,如果不知道您到底想要实现什么,就很难说清楚。
  • @MisterMiyagi 我有两组元组,每组有任意数量的元组,每个元组不管哪个组总是由 4 个字符串组成。
  • @JayRage 每个元组是由四个字符还是由四个字符串组成?字母是整个 UTF-8、ASCII、字母数字、小写字母还是更少?每个集合的元组是否存在重叠?

标签: python-3.x set tuples


【解决方案1】:

您可以为此使用熊猫。 Pandas 使用 C 绑定进行了优化,运行速度非常快。

df1

0   1   2   3
0   a   b   c   e
1   d   e   f   h
2   x   e   f   h
3   y   u   d   h

df2

0   1   2   3   4   5
0   a   b   c   d   None    None
1   d   e   f   g   None    None
2   m   n   o   p   None    None
3   b   c   d   y   u   d

我在上面假设元组的长度可能不同。

import pandas as pd
df1 = pd.DataFrame([tuple("a", "b", "c", "e"), tuple("d", "e", "f", "h"), tuple("x", "e", "f", "h"), tuple("y", "u", "d", "h") ])
df2 = pd.DataFrame([tuple("a", "b", "c", "d"), tuple("d", "e", "f", "g"), tuple("m", "n", "o", "p"), tuple("b", "c", "d", "y", "u", "d")])


# checks if the first 3 column values are in the second frame
df1[[0,1,2]].isin(df2).any(axis=1)


0     True
1     True
2    False
3     True
dtype: bool

所以它在第二个数据帧的 any 位置匹配 abc、def 和 yud。您可以推广这种方法来查找第一个数据帧的子集,而不是 cols 0:2。这可能看起来像这样:

for col_max in range(0, len(df1.columns)):
    col_names = [col_index for col_index in range(0, col_max)]
    print(df1[col_names].isin(df2).any(axis=1))

【讨论】:

  • 哇!不知道这可能是这样的!不错的图书馆!
  • 在我的情况下,我尝试过:df1 = pd.DataFrame(s1) df2 = pd.DataFrame(s2) print(df1[[0, 1, 2]].isin(df2)。 any(axis=1)) 然而,这会导致不同的结果,有时没有真,有时全假,有时是正确的结果。有没有可能,这取决于集合中的元组是如何排序的?
  • 集合是无序的——“无序意味着当我们显示集合的元素时,它会以随机顺序出现。”。当我将集合 {('a', 'b', 'c', 'd'), ('d', 'e', 'f', 'g'), ('m', 'n', 'o', 'p')} 加载到数据框中时,元组 ('a', 'b', 'c', 'd') 最终成为最后一行,但您希望它根据打印时集合的顺序位于第一行。你可以通过list(set(tuples 来维持秩序。
  • @forgetso 是的,这就是我读过的内容,但是你的方法对我不起作用,我得到奇怪的结果(每次运行程序时都会改变)使用 print( df1[[0, 1, 2]].isin(df2).any(axis=1))
  • 创建集合后,将它们转换为列表list1 和list2。订单将被固定。看看顺序。然后运行传入新创建的列表的数据帧命令,例如df1 = pd.DataFrame(list1) 和 df2 = pd.DataFrame(list2)。 df1[[0, 1, 2]].isin(df2).any(axis=1) 的输出将直接与list1 和list2 的顺序相关联。
猜你喜欢
  • 2021-08-06
  • 1970-01-01
  • 2023-03-18
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 2017-03-03
  • 2010-10-06
相关资源
最近更新 更多