【问题标题】:List of indices of tuples of tuples that contain certain tuples包含某些元组的元组的元组索引列表
【发布时间】:2020-12-25 15:55:36
【问题描述】:

我有一个列表 list1 的 3 个元组子列表,例如

[[(['A', 'B', 'A'], ['B', 'O', 'A']),
  (['A', 'B', 'A'], ['B', 'A', 'O']),
  (['A', 'B', 'O'], ['B', 'O', 'A']),
  (['A', 'B', 'O'], ['B', 'A', 'O']),
  (['A', 'B', 'A'], ['B', 'O', 'A']),
  (['A', 'B', 'A'], ['B', 'A', 'O'])],
 [(['A', 'B', 'A'], ['B', 'A', 'A']),
  (['A', 'B', 'O'], ['B', 'A', 'A']),
  (['A', 'B', 'A'], ['B', 'A', 'A'])],
 [['A', 'B', 'A'], ['A', 'B', 'O']],
 [['A', 'B', 'B']],
 [['B', 'A', 'A']]]

假设list2 = ['A', 'B', 'A']. 我的目标是获取list1 中包含元组list2 的任何元组对(或单例元组)的索引列表。我尝试如下使用enumerate函数但结果不正确

print([i for i, j in enumerate(bigset) if ['A', 'B', 'A'] in j[0] or 
       ['A', 'B', 'A'] == j[0] or [['A', 'B', 'A']] in j[0]])

谁能帮我解决这个问题?由于list1 中出现的元组的不同大小的元组不匹配,我很困惑。

我的另一个问题是:我想在list1 中找到三元素列表的总数。因此,如果我手动操作,答案是22。但是如何在代码中做到这一点?我想我们需要使用两个for 循环?

预期输出对于上面的list1 和给定的list2,我们会得到包含list2 的索引列表是[0,1,5,6,7,9,10]

【问题讨论】:

  • 你有一个包含五个列表的列表,内部列表有时包含元组,包含列表。请为list1 分享您想要的确切输出。
  • 发布的代码中没有“元组的元组”。您所拥有的主要是带有一些元组的列表。几乎不可能像发布的那样阅读。为什么不把长队分开?
  • 非常杂乱无章。您最好将其更改为更友好的格式(例如元组列表的列表)并查看您想要实现的目标
  • @timgeb:我显示了我想要的list1. 的确切输出,你能帮忙吗?我有tuples 的原因是因为我使用函数list(itertools.product()) 来创建这些对。
  • @TomKarzes:请将每对元组视为大列表中的一个元素。我只关心在list2. 中获取包含给定元组的那些对的位置列表你现在更清楚了吗?

标签: python python-3.x tuples


【解决方案1】:

由于深度未知和/或缺乏已知的数组展平操作,有点不合常规的方法 - 我会尝试使用正则表达式:

import re

def getPos(el, arr):
    el=re.escape(str(el))
    el=f"(\({el})|({el}\))"
    i=0
    for s in re.finditer(r"\([^\)]+\)", str(arr)):
        if(re.match(el,s.group(0))):
            yield i
        i+=1

产量:

>>> print(list(getPos(list2, list1)))

[0, 1, 4, 5, 6, 8, 9]

(我相信这是您想要的实际结果)。

【讨论】:

  • 非常感谢您的帮助。你用过 Python 3 吗?我试过你的代码,但我得到了错误el=f"(\({el})|({el}\))" ^ SyntaxError: invalid syntax
  • 是的,python3 - 对于早期版本,只需这样做:el="(\({0})|({0}\))".format(el)
【解决方案2】:

如果我们首先将您的 list1 整理成更友好的格式,它对您的实施是否有用?如果是这样,您可以通过一种非常简单的方式做到这一点:

遍历list1的每个元素,如果元素本身是一个大的元组列表,那么我们要进一步解包。如果元素是一个元组(因此该元组的第一个元素是一个列表),或者它本身就是您的 3 元素列表之一,那么我们只想按原样附加它。

nice_list = []
for i in list1:
    if type(i[0]) == str or type(i[0]) == list:
        # i.e. i is one of your 3-element lists, or a tuple of lists
        nice_list.append(i)
    else:
        #If i is still a big list of other tuples, we want to unpack further
        for j in i:
            nice_list.append(j)

然后您可以更轻松地搜索索引:

for i, idx in zip(nice_list, range(len(nice_list))): 
    if ['A', 'B', 'A'] in i: 
        print(idx) #Or append them to a list, whatever you wanted to do

对于您关于查找有多少个 3 元素列表的问题的不太优雅的解决方案,是的,您可以使用 for 循环:

no_of_lists = 0
for n in nice_list:
    if type(n) == tuple:
        no_of_lists += len(n)
    elif type(n) == list and type(n[0]) == list:
        # if it is a list of lists
        no_of_lists += len(n)
    elif type(n) == list and type(n[0]) == str:
        #if it is a 3-element list
        no_of_lists_lists += 1
print('Number of 3-element lists contained:', no_of_lists)

编辑:要回答您在 cmets 中提出的关于 for n in nice_list 部分如何工作的问题,这只是遍历列表的每个元素。要探索这一点,请尝试编写一些代码来打印出 nice_list[0]nice_list[1] 等,或者使用 for 循环打印出每个 n,这样您就可以看到它的样子。例如,您可以这样做:

for n in nice_list:
    print(n)

了解它是如何工作的。

【讨论】:

  • 您能澄清一下If 的情况吗?在这种情况下,strlist 是什么意思?
  • 非常感谢您的帮助。这太棒了!我尝试了你的代码来查找有多少个 3 元素列表,显然结果是 21。而不是 22。我认为它可能不计算 [['A', 'B', 'A'], ['A', 'B', 'O']][['A', 'B', 'B']] 类型的元素
  • 对不起,当我第一次这样做时,它按预期返回了 22!让我进去修一下吧
  • 另一个添加的问题。如果我想定义一个变量 b[i] 使得如果第一个子列表的第一个元组元素为 2 则 b[1] = 2(否则 b[1]=1),如果第二个子列表的第一个元组元素为 b[2] = 2第一个子列表的元组元素是 2,依此类推,那么我将 list1 的预期输出为 [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1]. 你能帮我实现这个目标吗?
  • 这很简单,您的第一个问题只需 b = [len(i) for i in nice_list] ,第二个问题只需 len(b)。另外,如果对您有帮助,请记得投票/将答案标记为正确,这对我们这些相对较新的人真的很有帮助!
【解决方案3】:

好的,到此为止

这使用递归是因为我们不知道你的list1 的深度所以索引会这样计算:

0,1
2,3,4,
6,7
8,
9,10,11,12

等...(与您将其写在 1 行中的顺序相同)

这里的结果将是:

[0, 2, 8, 10, 12, 16, 18]

现在是代码

def foo(l,ref):
    global s
    global indexes
    for items in l:  #if it's an element of 3 letters
        if len(items)== 3 and len(items[0])==1:
            if items == ref: 
                indexes.append(s) #save his index if it match the ref
            s+= 1  #next index
        else: #We need to go deeper
            foo(items,ref)
    return(s)
          
        
list1 = [[(['A', 'B', 'A'], ['B', 'O', 'A']),
  (['A', 'B', 'A'], ['B', 'A', 'O']),
  (['A', 'B', 'O'], ['B', 'O', 'A']),
  (['A', 'B', 'O'], ['B', 'A', 'O']),
  (['A', 'B', 'A'], ['B', 'O', 'A']),
  (['A', 'B', 'A'], ['B', 'A', 'O'])],
 [(['A', 'B', 'A'], ['B', 'A', 'A']),
  (['A', 'B', 'O'], ['B', 'A', 'A']),
  (['A', 'B', 'A'], ['B', 'A', 'A'])],
 [['A', 'B', 'A'], ['A', 'B', 'O']],
 [['A', 'B', 'B']],
 [['B', 'A', 'A']]]

list2 = ['A', 'B', 'A']
indexes = []
s=0
count= foo(list1,list2)
print(indexes)

s 是我们正在处理的索引 count 是元素 (22) 的总量。 Indexes 是你想要的索引列表。

这项工作即使您制作了 list3 = [list1,list1,[list1,[list1],list1]] ,您也可能想尝试一下。

祝你现在就结束你的脚本。

【讨论】:

    猜你喜欢
    • 2016-12-23
    • 2022-09-27
    • 1970-01-01
    • 2016-06-27
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    相关资源
    最近更新 更多