我有一组对象,我想使用lambda表达式或某种条件删除集合的值。
我会这样做:
def pop(container, cond):
value = None
removed = False
for x in container:
if cond(x):
value = x
removed = True
container.remove(x)
break
if not removed:
raise Exception('No value to pop')
return value
示例用例是:
compare_object = {"price": 100, "quantity": 1, "product_id": 2}
objs = set([....])
def comparison(obj):
def wrap(obj2):
return (
obj2['price'] == obj['price'] and
obj2['quantity'] == obj['quantity'] and
obj2['product_id'] == obj['product_id']
)
similar_obj = pop(objs, comparison(compare_object))
这样,我们可以从一个集合中获得一个类似的对象,因此在调用该方法后,该集合将被减少。
我想知道是否有一种更简单的方法可以使用python中已有的实际数据结构来实现这一点,而不是在大型集合上进行循环,这在大集合上可能很昂贵?
答案 0 :(得分:2)
您可以从该条件创建for
(或者对于Python 2 filter
)而不是复杂的itertools.ifilter
循环,并从该过滤器中删除next
元素。
def pop(container, cond):
try:
value = next(filter(cond, container))
container.remove(value)
return value
except StopIteration:
raise Exception("No Value to pop")
示例:
>>> lst = [1,2,3,4,5]
>>> cond = lambda x: x % 2 == 0
>>> pop(lst, cond)
2
>>> pop(lst, cond)
4
>>> pop(lst, cond)
Exception: No Value to pop
>>> lst
[1, 3, 5]
或者您可以通过立即返回找到的值来简化您的功能:
def pop(container, cond):
for x in container:
if cond(x):
container.remove(x)
return x
raise Exception('No value to pop')
答案 1 :(得分:1)
您的pop()
方法基本上与已构建的filter()
重复,并在生成的next()
对象上调用filter
。您可以将代码简化为:
compare_object = {"price": 100, "quantity": 1, "product_id": 2}
objs = set([....])
def comparison(obj):
def wrap(obj2):
return (
obj2['price'] == obj['price'] and
obj2['quantity'] == obj['quantity'] and
obj2['product_id'] == obj['product_id']
)
similar_obj = next(filter(comparison(compare_object), objs))
如果没有匹配,这将引发StopIteration
。
至于性能:如果你有一个集合,根据定义是无序的,并且你的条件必须检查每个条目,那么就无法迭代所有元素。但由于您只检索第一次出现,因此几乎不需要遍历整个集合。由于filter()
懒惰地评估其结果,因此它的行为方式相同,只会迭代整个集合,直到找到第一个匹配。
答案 2 :(得分:0)
由于某些原因,我决定采用defaultdict
变体。而不是使用set
。我只是将数据存储在带有列表的defaultdict中。
设置容器:
container = defaultdict(list)
for exp_line in exp_lines:
container[(
exp_line.unit_amount,
exp_line.unit_quantity,
exp_line.product_id,
exp_line.uom_id
)].append(exp_line)
从容器弹出:
obj = container[(
-(aal.amount/aal.unit_amount),
aal.unit_amount,
aal.product_id,
aal.product_uom_id
)].pop()
我用这种方法看到的唯一缺点是,没有简单的方法可以知道容器是否为空。但是尝试从空列表弹出将引发异常,就像预期的那样,数据实际上已从容器中删除。
由于条件相当严格,因此#34;就好像我使用单一条件一样,这样就简单得多了。但如果我不得不使用" custom"无法进行哈希处理的密钥。其他答案用" next / filter"我猜是一个更好的工具。
确实没有算法。