Home > front end >  Python breaking down list in loop based on total
Python breaking down list in loop based on total

Time:02-02

I have what I think is a fairly complicated problem to solve. For each item in a list I must get a total area. When the area of enough of those items meets a total area, those items must be split into a separate list. The process will then continue for the subsequent items in the list.

The code looks something like this, but does not work yet:

all_areas = [1,2,3,4,5,6,7,8,9]

def get_area(n):
  # in my actual code the function does more than just return n as it is.
  return n

for i in all_areas:
  total_area=0
  ids=[]
  while total_area < 20:
    area = get_area(i)
    total_area =area
    ids.append(i)
  else:
    # pass along ids before resetting counters
    call_another_function(ids)
    total_area=0
    ids=[]

With 20 as the threshold and with the given parameters, I am intending the call_another_function will be called once with [1,2,3,4,5,6] and then another time with [7,8,9]. The loop will then finish. Some help with this problem would be appreciated.

I was also wondering if this would be a suitable circumstance to use yield and generators? These seem to be a useful capability of Python that I have not ever had to use before.

CodePudding user response:

Generator solution:

If you are looking to learn generators, here's a way to use them:

def area_up_to(it, n):
    total_area = 0
    ids = []
    for x in it:
        total_area  = get_area(x)
        ids.append(x)
        if total_area >= n:
            yield ids
            total_area = 0
            ids = []
    if ids:
        yield ids

To use it, call the function to produce a generator:

area_gen = area_up_to(all_areas, 20)

Then you can iterate it or call next(area_gen) to get the next set:

for x in area_gen:
    print(x)

Output:

[1, 2, 3, 4, 5, 6]
[7, 8, 9]

Fixing your code:

You had some logic issues and a wild while..else in there, but this works:

total_area=0
ids=[]
for i in all_areas:
    area = get_area(i)
    total_area  = area
    ids.append(i)
    if total_area > 20:
        # pass along ids before resetting counters
        print(ids)
        total_area=0
        ids=[]
if ids:
    print(ids)

CodePudding user response:

Here is a method. I'm not sure I see the value in using a generator here, but it may be helpful depending on the wider implementation:

all_areas = [1, 2, 3, 4, 5, 6, 7, 8, 9]
thr = 20
groups = []

while all_areas:
    total = 0
    cur = []
    while total < thr:
        if not all_areas:
            break
        x = all_areas.pop(0)
        total  = x
        cur.append(x)
    groups.append(cur)

print(groups)

output:

[[1, 2, 3, 4, 5, 6], [7, 8, 9]]
  •  Tags:  
  • Related