簡體   English   中英

有效地按 Python 3.6+ 中的位置訪問字典項

[英]Accessing dictionary items by position in Python 3.6+ efficiently

我知道字典在 Python 3.6+ 中是按插入順序排列的,作為 3.6 中的實現細節和 3.7+ 中的官方實現細節。

鑒於它們是有序的,似乎沒有方法可以按插入順序檢索字典的i項目。 唯一可用的解決方案似乎具有 O( n ) 復雜度,要么:

  1. 通過 O( n ) 過程轉換為列表,然后使用list.__getitem__
  2. 在循環中enumerate字典項並在達到所需索引時返回值。 同樣,時間復雜度為 O( n )。

由於從list獲取項目的復雜度為 O(1),有沒有辦法用字典實現相同的復雜度? 使用常規dictcollections.OrderedDict都可以。

如果不可能,是否存在阻止這種方法的結構原因,或者這只是尚未考慮/實施的功能?

對於OrderedDict它本質上是O(n)因為排序記錄在鏈表中

對於內置字典,有一個向量(一個連續的數組)而不是一個鏈表,但最后幾乎是一樣的:向量包含一些“啞元”,特殊的內部值,意味着“沒有鍵存儲在這里”或“曾經存儲在這里但不再存儲的密鑰”。 這使得,例如,刪除一個密鑰非常便宜(只需用一個虛擬值覆蓋該密鑰)。

但是,如果不在此基礎上添加輔助數據結構,就無法跳過虛擬對象而不一次一個地跳過它們。 因為 Python 使用一種開放尋址形式來解決沖突,並將負載因子保持在 2/3 以下,所以至少有三分之一的向量條目虛擬的。 the_vector[i]可以在O(1)時間內訪問,但實際上與第 i 個非虛擬條目沒有可預測的關系。

根據@TimPeters 的回答,您無法在 O(1) 時間內按位置訪問字典項存在結構性原因。

如果您正在按鍵位置尋找 O(1) 查找,則值得考慮替代方案。 有 NumPy / Pandas 等 3rd 方庫提供了這樣的功能,特別是對於不需要指針的數字數組來說非常有效。

使用 Pandas,您可以構建一個具有獨特標簽的“類字典”系列,通過“標簽”或位置提供 O(1) 查找。 您犧牲的是刪除標簽時的性能,這會產生 O( n ) 成本,很像list

import pandas as pd

s = pd.Series(list(range(n)))

# O(n) item deletion
del s[i]
s.drop(i)
s.pop(i)

# O(1) lookup by label
s.loc[i]
s.at[i]
s.get(i)
s[i]

# O(1) lookup by position
s.iloc[i]
s.iat[i]

pd.Seriesdict替代品。 例如,如果該系列主要用作映射,則不會阻止重復鍵並且會導致問題。 但是,如果數據存儲在連續的內存塊中,如上例所示,您可能會看到顯着的性能改進。

也可以看看:

  1. 與常規 Python 列表相比,NumPy 有哪些優勢? .
  2. Pandas 中非唯一索引的性能影響是什么?
  3. Pandas DataFrame 搜索是線性時間還是常數時間?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM