[英]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.