Получение кортежа из коллекции кортежей на основе содержащегося значения

StackOverflow https://stackoverflow.com/questions/1047403

  •  20-08-2019
  •  | 
  •  

Вопрос

У меня есть структура данных, которая представляет собой набор таких кортежей:

things = ( (123, 1, "Floogle"), (154, 33, "Blurgle"), (156, 55, "Blarg") )

Каждый из первого и третьего элементов уникален для коллекции.

Я хочу получить конкретный кортеж, обратившись к третьему значению, например:

>>> my_thing = things.get( value(3) == "Blurgle" )
(154, 33, "Blurgle")

Должен быть лучший способ, чем написание цикла для проверки каждого значения одно за другим!

Это было полезно?

Решение

Если things это список, и вы знаете, что третий элемент уникален, а как насчет понимания списка?

>> my_thing = [x for x in things if x[2]=="Blurgle"][0]

Хотя под капотом я предполагаю, что он перебирает все значения и проверяет их по отдельности.Если вам это не нравится, как насчет изменения my_things структуру так, чтобы она была dict и использовать первое или третье значение в качестве ключа?

Другие советы

Цикл (или что-то на 100% эквивалентное, например, понимание списка или genexp) на самом деле является единственным подходом, если ваша структура внешнего уровня представляет собой кортеж, как вы указываете - кортежи по преднамеренной конструкции представляют собой чрезвычайно легкий контейнер с на самом деле почти никаких методов (всего несколько специальных методов, необходимых для реализации индексации, циклов и тому подобного ;-).

Молниеносный поиск — это характеристика словарей, а не кортежей.Разве вы не можете иметь словарь (в качестве основной структуры или в качестве дополнительной вспомогательной структуры), сопоставляющий «значение третьего элемента» искомому подкорпусу (или, возможно, его индексу в основном кортеже)?Это можно построить с помощью одного цикла, а затем обеспечить столько быстрых поисков, сколько вам нужно!

Если вы решите зациклиться, генэксп согласно комментарию Брайана и мой ответ на него будет более читабельным и в среднем, возможно, в два раза быстрее, чем listcomp (поскольку он выполняет только половину цикла):

my_thing = next(item for item in things if item[2] == "Blurgle")

что плавно читается как «следующий элемент в вещах, чей [2] подпункт равен Blurgle» (поскольку вы начинаете с самого начала, «следующий» элемент, который вы найдете, будет «первым» - и, в вашем случае, только -- подходящий).

Если вам нужно охватить случай, когда ни один элемент не соответствует предикату, вы можете пройти next второй аргумент (который он вернет при необходимости), в противном случае (без второго аргумента, как в моем фрагменте) вы получите исключение StopIteration, если ни один элемент не соответствует предикату - любое поведение может быть тем, что вы желаете (как вы говорите такой случай никогда не должен возникать, исключение выглядит подходящим для вашего конкретного приложения, поскольку рассматриваемое возникновение будет непредвиденной ошибкой).

если вам приходится выполнять этот тип поиска несколько раз, почему бы вам не преобразовать вещи в Things_dict один раз, тогда поиск будет проще и быстрее в дальнейшем

things = ( (123, 1, "Floogle"), (154, 33, "Blurgle"), (156, 55, "Blarg") )

things_dict = {}
for t in things:
    things_dict[t[2]] = t

print things_dict['Blarg']
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top