[英]Removing List from List of Lists with condition
I have this list of projects, and I want to remove it one by one start from last item to item-n until it reach some total value of budget = 325.000 我有这个项目列表,我想从最后一个项目到项目n一个接一个地删除它,直到它达到预算的总值= 325.000
from collections import namedtuple
Item = namedtuple('Item', 'region sector name budget target performance'.split())
sorted_KP = [Item(region='H', sector='2', name='H3', budget=7000.0, target=1.0, performance=4.0),
Item(region='H', sector='2', name='H10', budget=35000.0, target=15.0, performance=1.0),
Item(region='I', sector='2', name='I6', budget=50000.0, target=5.0, performance=0.40598931548848194),
Item(region='E', sector='4', name='E5', budget=75000.0, target=30.0, performance=0.0663966081766),
Item(region='C', sector='1', name='C1', budget=75000.0, target=50.0, performance=0.0308067750379),
Item(region='C', sector='1', name='C2', budget=75000.0, target=50.0, performance=0.0308067750379),
Item(region='C', sector='5', name='C4', budget=75000.0, target=50.0, performance=0.0308067750379),
Item(region='I', sector='2', name='I5', budget=100000.0, target=5.0, performance=0.40598931548848194),
Item(region='E', sector='4', name='E1', budget=100000.0, target=30.0, performance=0.0663966081766),
Item(region='D', sector='5', name='D21', budget=60000.0, target=4.0, performance=0.2479775110248),
Item(region='D', sector='5', name='D30', budget=10000.0, target=1.0, performance=0.1653183406832),
Item(region='D', sector='1', name='D23', budget=30000.0, target=20.0, performance=0.023659703723372342),
Item(region='C', sector='5', name='C3', budget=150000.0, target=75.0, performance=0.0308067750379),
Item(region='D', sector='5', name='D20', budget=30000.0, target=5.0, performance=0.0826591703416),
Item(region='H', sector='2', name='H6', budget=310576.0, target=1.0, performance=4.0),
Item(region='H', sector='3', name='H5', budget=9500.0, target=1.0, performance=0.1172008400616),
Item(region='E', sector='6', name='E3', budget=100000.0, target=30.0, performance=0.03747318294316411),
Item(region='G', sector='3', name='G17', budget=75000.0, target=20.0, performance=0.04132095963602382),
Item(region='C', sector='4', name='C5', budget=75000.0, target=25.0, performance=0.0308067750379),
Item(region='C', sector='2', name='C6', budget=30000.0, target=5.0, performance=0.0616135500758),
Item(region='C', sector='2', name='C7', budget=30000.0, target=5.0, performance=0.0616135500758),
Item(region='D', sector='6', name='D22', budget=65190.0, target=30.0, performance=0.020332158889648923),
Item(region='D', sector='5', name='D3', budget=100000.0, target=20.0, performance=0.0413295851708),
Item(region='D', sector='5', name='D4', budget=100000.0, target=20.0, performance=0.0413295851708),
Item(region='A', sector='1', name='A12', budget=25000.0, target=25.0, performance=0.00749432996938),
Item(region='A', sector='1', name='A13', budget=25000.0, target=25.0, performance=0.00749432996938),
Item(region='A', sector='3', name='A25', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='5', name='A26', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='1', name='A27', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='1', name='A29', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='3', name='A30', budget=4500.0, target=1.0, performance=0.02997731987752)]
But beside the total value, I have two others conditions of the item whether it should be removed or not. 但除了总价值之外,我还有另外两个项目的条件是否应该删除。
First, after the item is removed there still remain at least one item in the list of lists that represent the same region 首先,在删除项目之后,仍然存在代表相同区域的列表列表中的至少一个项目
Second, after the item is removed there still remain at least one item that represent the same sector 其次,在移除项目之后,仍然存在至少一个表示相同扇区的项目
For example, I can remove the last item because it represent region "A" and there left 5 items that also represent region "A". 例如,我可以删除最后一项,因为它代表区域“A”,剩下5项也代表区域“A”。 Also it represent sector "3" and there left 3 items that represent sector "3". 它也代表扇区“3”,留下3个代表扇区“3”的项目。
This removal and checking repeated until I reach total budget of removal at least 325.000 重复此删除和检查,直到我达到总移除预算至少325.000
I did this code, but I can not get what I need. 我做了这个代码,但我无法得到我需要的东西。 Please help me to correct it. 请帮我纠正一下。
from collections import Counter
unpack = []
for item in sorted_KP:
item_budget = item[3]
sum_unpack = sum(item[3] for item in unpack)
budget = 325000
remaining = []
for item in sorted_KP:
if item not in unpack:
remaining.append(item)
region_el = [item[0] for item in remaining]
counter_R_el = Counter(region_el)
sector_el = [item[1] for item in remaining]
counter_S_el = Counter(sector_el)
if counter_R_el >= 1 or counter_S_el >= 1:
if sum_unpack <= budget:
unpack.append(item)
for item in unpack:
print "\t", item
Here is what I got with my code, item-25 is still removed when it should not: 这是我的代码,第25项仍然删除时,它不应该:
unpack =Item(region='A', sector='3', name='A30', budget=4500.0, target=1.0, performance=0.02997731987752)
Item(region='A', sector='1', name='A29', budget=4500.0, target=1.0, performance=0.02997731987752)
Item(region='A', sector='1', name='A27', budget=4500.0, target=1.0, performance=0.02997731987752)
Item(region='A', sector='5', name='A26', budget=4500.0, target=1.0, performance=0.02997731987752)
Item(region='A', sector='3', name='A25', budget=4500.0, target=1.0, performance=0.02997731987752)
Item(region='A', sector='1', name='A13', budget=25000.0, target=25.0, performance=0.00749432996938)
Item(region='A', sector='1', name='A12', budget=25000.0, target=25.0, performance=0.00749432996938)
Item(region='D', sector='5', name='D4', budget=100000.0, target=20.0, performance=0.0413295851708)
Item(region='D', sector='5', name='D3', budget=100000.0, target=20.0, performance=0.0413295851708)
Item(region='D', sector='6', name='D22', budget=65190.0, target=30.0, performance=0.020332158889648923)
Item-25 (project name: "A12") can not be removed even though we still have budget to be removed, because if it was remove, there'll be no more item represent region "A", and so on. 项目25(项目名称:“A12”)无法删除,即使我们仍有预算要删除,因为如果删除,则不再有项目代表区域“A”,依此类推。
While the solution should be: 虽然解决方案应该是:
unpack = [Item(region='A', sector='3', name='A30', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='1', name='A29', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='1', name='A27', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='5', name='A26', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='3', name='A25', budget=4500.0, target=1.0, performance=0.02997731987752),
Item(region='A', sector='1', name='A13', budget=25000.0, target=25.0, performance=0.00749432996938),
Item(region='D', sector='5', name='D4', budget=100000.0, target=20.0, performance=0.0413295851708),
Item(region='D', sector='5', name='D3', budget=100000.0, target=20.0, performance=0.0413295851708),
Item(region='D', sector='6', name='D22', budget=65190.0, target=30.0, performance=0.020332158889648923),
Item(region='C', sector='2', name='C7', budget=30000.0, target=5.0, performance=0.0616135500758)]
Thank you in advance for your help 预先感谢您的帮助
Updating the answer as when I actually tried to run it I found a few other problems: 在我实际尝试运行它时更新答案我发现了一些其他问题:
for item in sorted_KP
uses the same item
counter as the outer loop and overwrites it - always attempting to remove the A30
(last) item for item in sorted_KP
使用与外部循环相同的item
计数器并覆盖它 - 始终尝试删除A30
(最后)项目 item2
in the inner loop I had to also reverse the outer loop order (ie start removal from the last line). 当切换到内循环中的item2
,我还必须反转外循环顺序(即从最后一行开始删除)。 TypeError: unorderable types: Counter() >= int()
- need to pick the specific count inside matching the item's region or sector as needed 区域/扇区计数器比较不正确,导致TypeError: unorderable types: Counter() >= int()
- 需要根据需要选择匹配项目区域或扇区的特定计数 and
your 2 extra conditions, not or
them 结合我之前的回答:你需要and
你的2个额外条件,不是or
他们 > 1
, not >= 1
并入@wwii的评论 - 实际上,计数器比较需要> 1
,而不是>= 1
The actual tested code: 实际测试的代码:
>>> for item in sorted_KP[::-1]:
... item_budget = item[3]
... sum_unpack = sum(item[3] for item in unpack)
... budget = 325000
... remaining = []
... for item2 in sorted_KP:
... if item2 not in unpack:
... remaining.append(item2)
... region_el = [item[0] for item in remaining]
... counter_R_el = Counter(region_el)
... sector_el = [item[1] for item in remaining]
... counter_S_el = Counter(sector_el)
... if counter_R_el[item.region] > 1 and counter_S_el[item.sector] > 1:
... if sum_unpack <= budget:
... unpack.append(item)
...
>>>
>>> for item in unpack:
... logging.error(item)
...
ERROR:root:Item(region='A', sector='3', name='A30', budget=4500.0, target=1.0, performance=0.02997731987752)
ERROR:root:Item(region='A', sector='1', name='A29', budget=4500.0, target=1.0, performance=0.02997731987752)
ERROR:root:Item(region='A', sector='1', name='A27', budget=4500.0, target=1.0, performance=0.02997731987752)
ERROR:root:Item(region='A', sector='5', name='A26', budget=4500.0, target=1.0, performance=0.02997731987752)
ERROR:root:Item(region='A', sector='3', name='A25', budget=4500.0, target=1.0, performance=0.02997731987752)
ERROR:root:Item(region='A', sector='1', name='A13', budget=25000.0, target=25.0, performance=0.00749432996938)
ERROR:root:Item(region='D', sector='5', name='D4', budget=100000.0, target=20.0, performance=0.0413295851708)
ERROR:root:Item(region='D', sector='5', name='D3', budget=100000.0, target=20.0, performance=0.0413295851708)
ERROR:root:Item(region='D', sector='6', name='D22', budget=65190.0, target=30.0, performance=0.020332158889648923)
ERROR:root:Item(region='C', sector='2', name='C7', budget=30000.0, target=5.0, performance=0.0616135500758)
>>>
Assume that you are using Python 2 as you use print
without ()
. 假设您在使用print
without ()
使用Python 2。
See the comments in the modified code: 请参阅修改后的代码中的注释:
unpack = []
for item in sorted_KP[::-1]: # loop the items in reverse order
#item_budget = item[3] # variable not used
sum_unpack = sum(item[3] for item in unpack)
budget = 325000
remaining = []
for x in sorted_KP: # don't use 'item' here as in Python 2, it will modify the variable 'item' in the outer loop
if x not in unpack:
remaining.append(x)
region_el = [x[0] for x in remaining] # don't use 'item' here as well
counter_R_el = Counter(region_el)
sector_el = [x[1] for x in remaining] # don't use 'item' here as well
counter_S_el = Counter(sector_el)
#if counter_R_el >= 1 or counter_S_el >= 1: # note that result is always True in Python 2
if counter_R_el[item.region] > 1 and counter_S_el[item.sector] > 1: # check '> 1' instead of '>= 1', and use 'and' instead of 'or'
if sum_unpack <= budget:
unpack.append(item)
for item in unpack:
print "\t", item
My proposed solution: 我建议的解决方案
budget = 325000
sum = 0 # accumulated budget of removed items
removed_KP = [] # holds the removed items
for item in sorted_KP[::-1]:
# stop checking if over-budget
if sum >= budget: break
# check whether there are items with same region and sector
rcnt = scnt = 0
for tmp in sorted_KP:
if tmp.region == item.region: rcnt += 1
if tmp.sector == item.sector: scnt += 1
if scnt > 1 and rcnt > 1:
# this item can be removed based on the constraints
sorted_KP.remove(item)
removed_KP.append(item)
sum += item.budget
# print the removed items
for item in removed_KP:
print(item)
I couldn't easily sort through your code. 我无法轻松整理您的代码。 if counter_R_el >= 1 or counter_S_el >= 1:
just can't work, you can't compare a Counter() to an int(). if counter_R_el >= 1 or counter_S_el >= 1:
只是无法工作,则无法将Counter()与int()进行比较。 It also looks like you continually remake/reset things in your loop suite and it became confusing. 它看起来像你不断重制/重置你的循环套件中的东西 ,它变得令人困惑。
You seem to be on the right track. 你似乎走在了正确的轨道上。
Here is what I came up with: 这是我想出的:
import collections, operator
Item = collections.namedtuple('Item', ['region', 'sector', 'name',
'budget', 'target', 'performance'])
a = [Item(region='H', sector='2', name='H3', budget=7000.0, target=1.0, performance=4.0),
Item(region='H', sector='2', name='H10', budget=35000.0, target=15.0, performance=1.0),
Item(region='I', sector='2', name='I6', budget=50000.0, target=5.0, performance=0.40598931548848194),
.....]
budget = 325000
# sort highest to lowest cost
a.sort(key = operator.attrgetter('budget'), reverse = True)
project_cost = sum(item.budget for item in a)
# constraint counters
region_count = collections.Counter(item.region for item in a)
sector_count = collections.Counter(item.sector for item in a)
# iterate over a copy of the list
b = a.copy()
for item in b:
if project_cost <= budget:
break
# check item against constraints
if region_count[item.region] > 1 and sector_count[item.sector] > 1:
# remove the item from the original list
a.remove(item)
# uodate the counters and cost
region_count[item.region] -= 1
sector_count[item.sector] -= 1
project_cost -= item.budget
a
contains the items that meet the constraints and have a total cost less than the budget. a
包含符合约束条件且总成本低于预算的项目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.