Список индексов кортежей кортежей, которые содержат определенные кортежи

#python #python-3.x #tuples

#python #python-3.x #кортежи

Вопрос:

У меня есть список 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 .

Еще один вопрос, который у меня есть: я хочу найти общее количество списков из 3 элементов в list1 . Итак, если я сделаю это вручную, ответ будет 22 . Но как это сделать в коде? Я думаю, нам нужно использовать два for цикла?

Ожидаемый результат Для list1 приведенного выше list2 мы получили бы список индексов, содержащих list2 is [0,1,5,6,7,9,10] .

Комментарии:

1. У вас есть список из пяти списков, внутренние списки, иногда содержащие кортежи, содержащие списки. Пожалуйста, поделитесь точным результатом, который вы хотите получить list1 .

2. В опубликованном коде нет «кортежей кортежей». В основном у вас есть списки с несколькими кортежами здесь и там. Это почти невозможно прочитать как опубликовано. Почему бы не разделить длинную строку?

3. Это очень неорганизованно. Вам лучше изменить его на более удобный формат (например, список списков кортежей) и пересмотреть, чего вы хотите достичь

4. @timgeb: Я показал точный результат, который мне нужен list1. Можете ли вы, пожалуйста, помочь? Причина, по которой у меня есть tuples , заключается в том, что я использую функцию list(itertools.product()) для создания этих пар.

5. @TomKarzes: пожалуйста, рассматривайте каждую пару кортежей как элемент в большом списке. Меня интересует только получение списка позиций тех пар, которые содержат данный кортеж в list2. Теперь вам это понятнее?

Ответ №1:

Хорошо, итак, поехали

Это использует рекурсию, потому что мы не знаем глубину вашего 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]] , вы можете попробовать это.

Желаю удачи в завершении вашего сценария сейчас.

Ответ №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)
  

Редактировать: чтобы ответить на вопрос, который вы задали в комментариях о том, как работает for n in nice_list часть, это просто перебирает каждый элемент списка. Чтобы изучить это, попробуйте написать некоторый код для вывода на печать nice_list[0] , nice_list[1] и т.д. Или цикл for, который выводит каждый из них n , чтобы вы могли увидеть, как это выглядит. Например, вы могли бы сделать:

 for n in nice_list:
    print(n)
  

чтобы понять, как это работает.

Комментарии:

1. не могли бы вы уточнить If условие? Что str и list в данном случае означают?

2. большое вам спасибо за вашу помощь. Это потрясающе! Я попробовал ваш код, чтобы определить, сколько существует списков из 3 элементов, и, по-видимому, результат равен 21. а не 22. Я думаю, что это может не учитывать элемент типа либо [['A', 'B', 'A'], ['A', 'B', 'O']] , либо [['A', 'B', 'B']]

3. Ах, извините за это, когда я сделал это в первый раз, он вернул 22, как и ожидалось! Позвольте мне просто зайти и исправить это

4. однако добавлен еще один вопрос. Если я хочу определить переменную b [i] так, чтобы b [1] = 2, если первые элементы кортежа первого подсписка равны 2 (и b [1] = 1 в противном случае), b [2] = 2, если вторые элементы кортежа первого подсписка равны 2, и так далее, тогда у меня был бы ожидаемый результат от list1 as [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1]. Можете ли вы помочь мне достичь этой цели?

5. Это довольно просто, только b = [len(i) for i in nice_list] для вашего первого вопроса, а затем len(b) для вашего второго. Также, пожалуйста, не забудьте проголосовать / отметить ответы как правильные, если они помогут вам, это действительно помогает тем из нас, кто является относительно новым!

Ответ №3:

Немного нетрадиционный подход из-за неизвестной глубины и / или отсутствия известной операции выравнивания массива — я бы попробовал с регулярным выражением:

 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]
  

(Я считаю, что это фактический результат, который вы хотите).

Комментарии:

1. Большое вам спасибо за вашу помощь. Вы использовали Python 3? Я попробовал ваш код, но я получил ошибку el=f"(({el})|({el}))" ^ SyntaxError: invalid syntax

2. Да, python3 — для более ранних версий просто сделайте : el="(({0})|({0}))".format(el)