【问题标题】:Retrieving a tuple from a collection of tuples based on a contained value根据包含的值从元组集合中检索元组
【发布时间】:2009-06-26 04:49:36
【问题描述】:

我有一个数据结构,它是这样的元组集合:

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

第一个和第三个元素对集合都是唯一的。

我要做的是通过引用第三个值来检索特定的元组,例如:

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

一定有比编写循环更好的方法来逐个检查每个值!

【问题讨论】:

  • 我选择了循环理解答案而不是 convert-to-dict 答案,因为数据集很小,我最终可能想要根据其他元素之一检索元组。
  • 应该注意它(通常)被称为“列表理解”而不是“循环理解”。挑剔?如果您不关心 Google 的好结果或任何结果,那就是在吹毛求疵。

标签: python tuples


【解决方案1】:

如果您的外层结构是元组,那么循环(或 100% 等效的东西,例如列表理解或 genexp)确实是唯一的方法,正如您所指出的那样 - 元组经过深思熟虑的设计,是一个非常轻量级的方法容器,实际上几乎没有任何方法(只是实现索引、循环等所需的少数特殊方法;-)。

快如闪电的检索是字典而不是元组的特性。难道你不能有一个字典(作为主要结构,或作为辅助结构)将“第三个元素的值”映射到你寻找的子元组(或者它在主元组中的索引,也许)?这可以用一个循环构建,然后提供尽可能多的快速搜索!

如果您选择循环,根据 Brian 的评论和我对它的回复,genexp 的可读性更高,平均速度可能比 listcomp 快两倍(因为它只执行了一半的循环):

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

读作“[2] 子项等于 Blurgle 的事物中的下一个项目”(当您从头开始时,您找到的“下一个”项目将是“第一个”——并且,在你的情况,只有一个合适的)。

如果你需要覆盖没有项目满足谓词的情况,你可以传递next第二个参数(如果需要它会返回),否则(没有第二个参数,如我的sn-p)如果没有项目符合谓词,您将得到一个 StopIteration 异常 - 任何一种行为都可能是您想要的(正如您所说的情况永远不会出现,异常看起来适合您的特定应用程序,因为有问题的发生将是意外的错误)。

【讨论】:

  • 我更感兴趣的是清楚地表达意图,而不是快速获得结果。使用 Python 的循环理解将循环减少到一行代码,这(就像 C 和 Perl 中的三元“?”)以维护程序员的挫败感为代价实现代码简洁:) 从快速的角度来看,字典的想法是明智的根据一个参数检索信息。感谢您对此的看法。
  • 我已经更新了我的代码来指向这个问题。如果我正在接受培训以接受我的工作的人不会像我一样费心去学习尽可能多的 Python,那不是我的问题。 #passiveaggressive
  • 几年后回到这一点,生成器理解现在确实看起来更具可读性。但是我拥有一两年 Python 的优势,并且不再被导致我之前评论的沮丧和愤怒所迷惑 :) 感谢您的明确解释!
【解决方案2】:

如果things 是一个列表,并且你知道第三个元素是 uniqe,那么列表推导式呢?

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

虽然在幕后,我假设它会遍历所有值并单独检查它们。如果您不喜欢这样,那么将my_things 结构更改为dict 并使用第一个或第三个值作为键怎么样?

【讨论】:

  • 在一般情况下,循环理解似乎是解决此问题的最简单方法。谢谢你的建议。
  • 如果您使用生成器推导,则可以避免遍历整个列表:"my_thing = (x for x in things if x[2]=="Blurgle").next()" -这只会迭代直到找到该项目。
  • 你是对的,Brian,除了在 2.6 和更高版本中 next(x for x in things if x[2]=='zap') 甚至比你的 2.4 兼容的想法更好!跨度>
【解决方案3】:

如果你必须多次进行这种类型的搜索,为什么不将 things 转换为 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']

【讨论】:

  • 在我需要多次检索一个值的情况下,转换为字典当然可以解决问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-01-28
  • 2013-10-22
  • 2013-09-01
  • 2017-06-17
  • 2020-12-25
  • 2019-11-03
  • 2023-03-09
  • 2022-12-13
相关资源
最近更新 更多