Есть ли в Python способ индексировать список контейнеров (кортежей, списков, словарей) по элементу контейнера?

1

Я провоцировал рецепт/пример, чтобы индексировать список кортежей, не внося изменения в метод декорирования, сортировки и декомпозиции.

Например:

l=[(a,b,c),(x,c,b),(z,c,b),(z,c,d),(a,d,d),(x,d,c) . . .]

Подход, который я использовал, заключается в построении словаря с использованием defaultdict второго элемента

from collections import defaultdict

tdict=defaultdict(int)

for myTuple in l:
    tdict[myTuple[1]]+=1

Затем мне нужно создать список, состоящий только из второго элемента в кортеже для каждого элемента в списке. Хотя существует несколько способов получить простой подход:

tempList=[myTuple[1] for myTuple in l]

а затем сгенерируйте индекс каждого элемента в tdict

indexDict=defaultdict(dict)
for key in tdict:
    indexDict[key]['index']=tempList.index(key)

Ясно, что это не очень Pythonic. Я пытался найти примеры или идеи, думая, что я должен использовать что-то магическое, чтобы получить индекс напрямую. Пока нет такой удачи.

Заметьте, я понимаю, что я могу взять мой подход немного более прямо и не генерировать tdict.

вывод может быть словарем с индексом

indexDict={'b':{'index':0},'c':{'index':1},'d':{'index':4},. . .}

После многого узнаю ответы Nadia, я думаю, что ответ отрицательный.

Пока работает ее ответ, я думаю, что это сложнее, чем нужно. Я просто

 def build_index(someList):
    indexDict={}
    for item in enumerate(someList):
        if item[1][1] not in indexDict:
           indexDict[item[1][1]]=item[0]
    return indexDict
  • 1
    Я запутался в том, что ты пытаешься сделать. Какой ваш желаемый результат? Ваш код не совсем работает - что считается в строке "tdict [myTuple [1]] + = count"?
  • 0
    Можете ли вы привести пример ожидаемого результата или структуры?
Показать ещё 1 комментарий
Теги:
list
indexing
containers

2 ответа

5
Лучший ответ

Это приведет к результату, который вы хотите

dict((myTuple[1], index) for index, myTuple in enumerate(l))

>>> l = [(1, 2, 3), (4, 5, 6), (1, 4, 6)]
>>> dict((myTuple[1], index) for index, myTuple in enumerate(l))
{2: 0, 4: 2, 5: 1}

И если вы настаиваете на использовании словаря для представления индекса:

dict((myTuple[1], {'index': index}) for index, myTuple in enumerate(l))

Результат будет:

{2: {'index': 0}, 4: {'index': 2}, 5: {'index': 1}}

ИЗМЕНИТЬ Если вы хотите справиться с ключевым столкновением, вам придется расширить решение следующим образом:

def build_index(l):
    indexes = [(myTuple[1], index) for index, myTuple in enumerate(l)]
    d = {}
    for e, index in indexes:
        d[e] = min(index, d.get(e, index))
    return d

>>> l = [(1, 2, 3), (4, 5, 6), (1, 4, 6), (2, 4, 6)]
>>> build_index(l)
{2: 0, 4: 2, 5: 1}

РЕДАКТИРОВАТЬ 2

И более обобщенное и компактное решение (в аналогичном определении sorted)

def index(l, key):
    d = {}
    for index, myTuple in enumerate(l):
        d[key(myTuple)] = min(index, d.get(key(myTuple), index))
    return d

>>> index(l, lambda a: a[1])
{2: 0, 4: 2, 5: 1}

Итак, ответ на ваш вопрос: да. В Python есть способ индексировать список контейнеров (кортежей, списков, словарей) элементом контейнера без предварительной обработки. Но ваш запрос на сохранение результата в словаре делает невозможным быть одним лайнером. Но здесь нет предварительной обработки. Список повторяется только один раз.

  • 0
    Это гладко Я вижу, это вопрос правильного мышления о проблеме. Я вижу, что это должно распространяться на любой субконтейнер в списке контейнеров. Круто и спасибо
  • 0
    На самом деле Надя это близко, но не совсем там. Попытайтесь добавить еще один кортеж с общим средним значением, скажем, add (2,4,6), и вы увидите, что вы получаете индекс для перечисления последнего значения - при записи в словарь вы перезаписываете значения. Но это дало мне достаточно, чтобы добраться туда, я думаю. Я понимаю ваш код, и так как я действительно хочу создать словарь ключа begin: value end: value, я о нем.
Показать ещё 3 комментария
0

Если я думаю, что это то, о чем вы просите...

l = ['asd', 'asdxzc']
d = {}

for i, x in enumerate(l):
    d[x] = {'index': i}
  • 3
    Почему бы не использовать перечислять для этого?
  • 0
    Не знал, что существует. Делает это немного проще.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню