在 Python 3 中获取“OrderedDict”第一项的最短方法
Posted
技术标签:
【中文标题】在 Python 3 中获取“OrderedDict”第一项的最短方法【英文标题】:Shortest way to get first item of `OrderedDict` in Python 3 【发布时间】:2014-01-30 12:23:11 【问题描述】:在 Python 3 中获取OrderedDict
第一项的最短方法是什么?
我最好的:
list(ordered_dict.items())[0]
又长又丑。
我能想到的:
next(iter(ordered_dict.items())) # Fixed, thanks Ashwini
但它不是很自我描述。
有更好的建议吗?
【问题讨论】:
使用列表是个坏主意。在您获得第一项之前,将填充整个列表。使用 next() 是最优的,因为 .items() 返回一个迭代器并且只会产生一个值。 最短路径是什么意思?字符数少? 我认为你也需要一个iter
调用:next(iter(d.items()))
因为.items
返回一个 View 对象。
@thefourtheye 是的,更少的字符,但希望也是惯用的。
我想知道next(iter(ordered_dict.items()))
这是否会推进迭代器。正如预期的那样,它不会推进迭代器!假设next(iter(ordered_dict.items()))
在O(1)
时间运行是否安全?
【参考方案1】:
可读性编程实践
一般来说,如果您觉得代码不是自描述的,通常的解决方案是将其分解为一个命名良好的函数:
def first(s):
'''Return the first element from an ordered collection
or an arbitrary element from an unordered collection.
Raise StopIteration if the collection is empty.
'''
return next(iter(s))
有了helper function,后面的代码就变得非常可读了:
>>> extension = 'xml', 'html', 'css', 'php', 'xhmtl'
>>> one_extension = first(extension)
从集合中提取单个值的模式
从 set、dict、OrderedDict、生成器或其他不可索引的集合中获取元素的常用方法是:
for value in some_collection:
break
和:
value = next(iter(some_collection))
后者很好,因为 next() 函数允许您在集合为空时指定默认值,或者您可以选择让它引发异常。 next() 函数也明确表示它正在请求下一项。
替代方法
如果你确实需要索引和切片等序列行为(比如索引多个元素),用list(some_collection)
转换成列表或者使用[itertools.islice()][2]
是很简单的事情:
s = list(some_collection)
print(s[0], s[1])
s = list(islice(n, some_collection))
print(s)
【讨论】:
我喜欢后一种选择,但您认为它比list(ordered_dict.items())[0]
更好吗?如果有什么我认为[0]
更明显。
@bedeabc list(ordered_dict.items())[0]
继续创建 dict 中所有项目的列表,然后获取该列表的第一项,然后丢弃该列表。你当然不想那样做。
@Mr_and_Mrs_D 我理解,并且已经习惯了 next(iter()) 模式,但是对于非常小的数据结构,我看不到优先考虑可读性的问题。
next(iter(self.items()))
会给你第一对(key, val)
【参考方案2】:
使用popitem(last=False)
,但请记住,它会从字典中删除条目,即具有破坏性。
from collections import OrderedDict
o = OrderedDict()
o['first'] = 123
o['second'] = 234
o['third'] = 345
first_item = o.popitem(last=False)
>>> ('first', 123)
有关详细信息,请查看collections 上的手册。它也适用于 Python 2.x。
【讨论】:
这对我来说是最好的办法,以防你不费心破坏字典 我想要一种非破坏性的方法。我该怎么做? 除此之外的东西:next(iter(self.items()))
给出(key, val)
【参考方案3】:
对OrderedDict
进行子类化和添加方法将是解决清晰度问题的方法:
>>> o = ExtOrderedDict(('a',1), ('b', 2))
>>> o.first_item()
('a', 1)
ExtOrderedDict
的实现:
class ExtOrderedDict(OrderedDict):
def first_item(self):
return next(iter(self.items()))
【讨论】:
不创建迭代器就没有什么吗?像 OD 的 api?【参考方案4】:可读的代码,保持 OrderedDict 不变,并且不会为了获取第一项而不必要地生成一个可能很大的列表:
for item in ordered_dict.items():
return item
如果 ordered_dict 为空,None 将被隐式返回。
在一段代码中使用的替代版本:
for first in ordered_dict.items():
break # Leave the name 'first' bound to the first item
else:
raise IndexError("Empty ordered dict")
对应于上面第一个示例的 Python 2.x 代码需要使用 iteritems() 代替:
for item in ordered_dict.iteritems():
return item
【讨论】:
next(iter(self.items()))
会给你第一对(key, val)
【参考方案5】:
第一条记录:
[key for key, value in ordered_dict][0]
最后记录:
[key for key, value in ordered_dict][-1]
【讨论】:
您好,感谢您对 *** 的贡献!虽然这可行且易于理解,但这是一种非常低效的方法,因为必须在内存中创建整个列表,然后才能提取所需的单个元素。 欢迎来到 *** @galaga4!你能帮我吗 - 看起来这将创建一个不需要的列表! 它效率低下的事实并没有使它错。这是一个完美的解决方案,可能是获得 OP 想要的短名单的简单方法。next(iter(self.items()))
会给你第一对(key, val)
以上是关于在 Python 3 中获取“OrderedDict”第一项的最短方法的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 3.5 中使用 aiohttp 获取多个 url