Хороший способ разделить список списков на две части, условно к значениям во внутреннем списке - PullRequest
0 голосов
/ 18 декабря 2018

Цель состоит в том, чтобы начать со следующего:

budget = 100
projects = [('B', 60), ('A', 35), ('F', 35), ('G', 35), ('C', 20), ('E', 20), ('D', 10)]

И достичь projects=[('B', 60), ('A', 35)] и remainingBudget =5.

Как программист JS, я заставил работать некоторыми способами следующее:

def findProjectsThatFitTheBudget(budget, projects):
    # find the most expensive projects that fit the given budget, and note the budget that remains after allocations
    remainingBudget = budget

    def shoulIncludeProject(name, cost):
        nonlocal remainingBudget
        if(cost <= remainingBudget):
            remainingBudget -= cost
            return True
        return False
    projects = list(
        takewhile(lambda project: shoulIncludeProject(project[0], project[1]), projects))

    # we now have the projects we are working with, and also the budget that remains unallocated

Интересно, каков самый питонный способ рефакторинга этого?Я застрял, по крайней мере, в следующем:

  1. Как мне написать простую лямбду вместо внешнего определения
  2. Как мне выполнить деструктуризацию в аргументах лямбды
  3. Как использовать and в режиме короткого замыкания с budget=-cost

Прекрасным решением могло бы быть:

projects = list(
    takewhile(lambda name, cost: cost<= budget and budget=-cost, projects))

с использованием andshort-circuit.

1 Ответ

0 голосов
/ 18 декабря 2018

Ничего плохого в простом цикле for, который закорачивается при исчерпании бюджета:

viable_projects = []
for project, cost in projects:
    budget -= cost
    if budget < 0:
        break
    viable_projects.append((project, cost))

viable_projects становится:

[('B', 60), ('A', 35)]
...