在 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)

从集合中提取单个值的模式

setdictOrderedDict、生成器或其他不可索引的集合中获取元素的常用方法是:

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 中获取所有超类

在Python 3.6中获取replace()的错误

在 Python 3.5 中使用 aiohttp 获取多个 url

在 Python 3 中获取“OrderedDict”第一项的最短方法

在 Python 3 中获取未绑定方法对象的定义类

在 Python 3.5 中使用 urllib 获取网页的最终重定向