![](/img/trans.png)
[英]How to filter objects with LineString field by distance to a Point?
[英]How to filter a collection of objects by field value?
如何在 Python 中按字段值組織和過濾對象集合? 我需要通過等於一個精確值和小於一個值來過濾。
以及如何有效地做到這一點? 如果我將我的對象存儲在一個列表中,我需要遍歷整個列表,可能包含數十萬個對象。
@dataclass
class Person:
name: str
salary: float
is_boss: bool
# if to store objects in a list...
collection = [Person("Jack", 50000, 0), ..., Person("Jane", 120000, 1)]
# filtering in O(n), sloooooow
target = 100000
filtered_collection = [x for x in collection if salary < target]
PS:實際上我的用例是按某個字段分組,即is_boss
並按另一個過濾,即salary
。 怎么做? 我應該在排序列表上使用itertools.groupby
並使我的對象具有可比性嗎?
如果您按排序順序維護您的list
(理想情況下,這意味着很少插入或刪除,因為中間list
插入/刪除本身就是O(n)
),您可以使用bisect
模塊找到低於給定薪水的Person
集合。
from bisect import bisect
from operator import attrgetter
# if to store objects in a list...
collection = [Person("Jack", 50000, 0), ..., Person("Jane", 120000, 1)]
collection.sort(key=attrgetter('salary')) # O(n log n) initial sort
# filtering searches in O(log n):
target = 100000
filtered_collection = collection[:bisect(collection, target, key=attrgetter('salary'))]
注意:各種bisect
模塊函數的key
參數僅在 3.10 中受支持。 在以前的版本中,您需要根據salary
為Person
定義豐富的比較運算符並搜索偽造的Person
對象,或者維護丑陋的單獨排序list
、僅salary
之一和Person
對象的並行list
.
要將單個元素添加到collection
中,您可以使用bisect
的insort
函數。 或者您可以將一堆項目批量添加到list
的末尾並使用與以前相同的key
(Python 的排序算法 TimSort,當集合大部分已經有序時,性能接近O(n)
,所以成本沒有你想象的那么高)。
我會注意到,在實踐中,這種場景(可以按多個字段任意排序的海量數據)通常需要數據庫; 您可能會考慮使用sqlite3
(如果需要,最終切換到更生產級的數據庫,如 MySQL 或 PostGres),在定義了適當的索引后,您可以在任何索引字段上執行O(log n)
SELECT
; 您可以在提取實際需要使用的數據時轉換為Person
對象。 真正的 DBMS 解決方案提供的 B 樹讓您在索引字段上的插入、刪除和選擇工作量為O(log n)
,而 Python 內置的集合類型讓您選擇; 只有插入/刪除或搜索中的一個可以真正是O(log n)
,而另一個是O(n)
。
數組有一個排序方法——你所要做的就是創建一個函數來判斷一個對象是否大於另一個對象——讓我告訴你
class Foo:
def __init__(bar):
this.bar = bar
fooArray = [Foo(10),Foo(8),Foo(9)]
def sortFoo(foo):
return foo.bar
fooArray.sort(key=sortFoo)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.