简体   繁体   English

从条件列表中删除列表

[英]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: 在我实际尝试运行它时更新答案我发现了一些其他问题:

  • the inner 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 (最后)项目
  • when switching to item2 in the inner loop I had to also reverse the outer loop order (ie start removal from the last line). 当切换到内循环中的item2 ,我还必须反转外循环顺序(即从最后一行开始删除)。
  • the region/sector counter comparison is incorrect, causing 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() - 需要根据需要选择匹配项目区域或扇区的特定计数
  • incorporated my earlier answer: you need to and your 2 extra conditions, not or them 结合我之前的回答:你需要and你的2个额外条件,不是or他们
  • incorporated @wwii's comment - indeed the counter comparisons need to be > 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. 你似乎走在了正确的轨道上。

  • To keep track of the number of regions and sectors collections.Counter() is a good choice. 要跟踪区域和行业集合的数量.Counter()是一个不错的选择。
  • look at each item in the list, and check if it meets your constraints 查看列表中的每个项目,并检查它是否符合您的约束
  • if removed, update the counters and the total cost 如果删除,请更新计数器和总费用

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM