在O(1)时间内从python3 dict检索任意密钥

在O(1)时间内从python3 dict检索任意密钥,python,python-3.x,iterator,Python,Python 3.x,Iterator,我需要从python dictionary对象中检索任意键。假设我有一本字典d。以下代码的时间复杂度是多少 k = next(iter(d.keys())) 在Python3中,d.key()在O(1)时间内,next()在O(1)时间内。iter()发生了什么? 这能在不占用额外空间的情况下在O(1)时间内完成吗?谢谢 使用iter(或其他逻辑,如生成器表达式、声明委托给dict的生成器函数、使用islice等)都是某种形式的包装器,它将\uuuuuuuuuuuuuuuuuuuuuuuuuu

我需要从python dictionary对象中检索任意键。假设我有一本字典
d
。以下代码的时间复杂度是多少

k = next(iter(d.keys()))
在Python3中,d.key()在O(1)时间内,next()在O(1)时间内。iter()发生了什么? 这能在不占用额外空间的情况下在O(1)时间内完成吗?谢谢

使用
iter
(或其他逻辑,如生成器表达式、声明委托给dict的生成器函数、使用
islice
等)都是某种形式的包装器,它将
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
方法和一些位置簿记添加到对象的视图
下一步(
这些主要工作是因为,但没有,so
iter
等调用
\uuuuu iter\uuuuu
方法,该方法返回一个iterable,该iterable确实有
\uuuuu next\uuuuuu
方法,并且是一个

每种情况都只是一个O(1)调用的包装器,因此一旦声明,它们都将在O(1)时间内运行


这是一个演示

首先创建一个相当大的字典(对于速度较慢的系统,这可能需要一段时间)

>>从uuid导入uuid4
>>>d={str(uuid4()):str(uuid4())表示范围(1000000)}
显示可以直接从现有方法执行此操作

下一步 “1273a529-d406-4076-8acc-8993f2613ad4” >>>类型(d.\uuuu iter\uuuuu())
其他对象

n1=iter(d)#iter功能 >>>n2=(k表示d中的k)#生成器表达式 >>>def y():#生成器委派 …来自d的收益 ... >>>进口itertools >>>i=itertools.islice(d,1)#从iterable中分割一个条目 >>>类型(n1) >>>类型(n2) >>>类型(y()) >>>第(i)类 每一个都可以用来读取第一个键

下一步(n1) “1273a529-d406-4076-8acc-8993f2613ad4” >>>下一个(n2) “1273a529-d406-4076-8acc-8993f2613ad4” >>>next(y()) “1273a529-d406-4076-8acc-8993f2613ad4” >>>下一(i) “1273a529-d406-4076-8acc-8993f2613ad4” 证明这些都提供了下一种方法

目录(d) “UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU类类类类类类类类类类类类类类类类类类,”,”,”,”,”,”,”,”,”UUUUUUUUUUUU","新的","减少","减少","减少","报告","新的","减少","减少","报告","设置","项目",eof、str、子类HOOK、clear、copy、fromkeys、get、items、keys、pop、popitem、setdefault、update、values'] >>>目录(d)中的“下一个” 假的 >>>目录(n1)中的“下一个” 真的 >>>目录(n2)中的“下一个” 真的 >>>目录(y()中的“\uuuuu下一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”) 真的 >>>目录(i)中的“下一个” 真的
最后,如果需要前N个值(而不仅仅是
next()
)中的第一个值),也可以在循环中有效地调用这些值,直到达到某个长度或将其切片为止,但是当形成列表或类似列表时,会产生一些额外的开销

导入itertools >>>清单(itertools.islice(d,5)) ['1273a529-d406-4076-8acc-8993f2613ad4','a920460d-a193-455c-979c-a91fd700f927','aeccb371-43d1-4690-8aaa-D6DE0CB3801','9aaf2a96-9ef4-4610-8723-8401008e190a','e4b450aa-50a2-409a-a5b2-ab88285eb770']

另请参见(第一次对您的答案发表评论,作者是抓取液

检查链接将
d.popitem()
对您有效吗?有副作用,会从字典中删除密钥。@jasonharper否,我不能删除任何密钥。@抓取液已检查,但仍有疑问。现在是O(n)时间?是的,现在是O(1)谢谢,但是我的问题有答案吗?@Luke每个案例都只是一个O(1)呼叫的包装器,所以一旦宣布,这些都将在O(1)时间内运行。哦,我明白了-我会把扩展的答案放在比第一条评论中链接的更相关的帖子上(你的!),但没有进一步链接them@Luke修正!如果我的答案更清楚,请建议编辑!
iter
不是生成器表达式,它返回一个迭代器。迭代器可能是生成器,但在本例中,它不是。
>>> list(itertools.islice(y(), 5))
['1273a529-d406-4076-8acc-8993f2613ad4', 'a920460d-a193-455c-979c-a91fd700f927', 'aeccb371-43d1-4690-8aaa-d6de0cbe3801', '9aaf2a96-9ef4-4610-8723-8401008e190a', 'e4b450aa-50a2-409a-a5b2-ab88285eb770']
>>> list(itertools.islice(n1, 5))
['1273a529-d406-4076-8acc-8993f2613ad4', 'a920460d-a193-455c-979c-a91fd700f927', 'aeccb371-43d1-4690-8aaa-d6de0cbe3801', '9aaf2a96-9ef4-4610-8723-8401008e190a', 'e4b450aa-50a2-409a-a5b2-ab88285eb770']
>>> list(itertools.islice(n2, 5))
['1273a529-d406-4076-8acc-8993f2613ad4', 'a920460d-a193-455c-979c-a91fd700f927', 'aeccb371-43d1-4690-8aaa-d6de0cbe3801', '9aaf2a96-9ef4-4610-8723-8401008e190a', 'e4b450aa-50a2-409a-a5b2-ab88285eb770']