Angenommen, dies ist meine Liste:

[5, 3, 13, 8, 1, 2, 6, 4, 10, 1, 12, 3, 7, 1, 4]

Ich möchte es in Stücke aufteilen, wobei eine maximale Summe von 12 berücksichtigt wird, wenn dies möglich ist, damit das Ergebnis wie folgt aussehen sollte:

[[5, 3], [13], [8, 1, 2], [6, 4], [10, 1], [12], [3, 7, 1], [4]]

Beachten Sie, dass der Code keine Ganzzahl löschen sollte, die größer als die maximale Summe ist (in unserem Fall 13), sondern in einer Unterliste isoliert bleibt.

Ich habe das mit diesem Code geschafft:

lst = [5, 3, 13, 8, 1, 2, 6, 4, 10, 1, 12, 3, 7, 1, 4]

start = 0
stop = 1
max_chunk_sum = 12
lst_count = len(lst)
result = []

while not stop > lst_count:
    chunk = lst[start:stop]
    chunk_sum = sum(chunk)
    chunk_count = len(chunk)

    if chunk_sum < max_chunk_sum:
        if stop != lst_count:
            stop += 1
        else:
            result.append(lst[start:stop])
            break
    else:
        if chunk_count == 1:
            result.append(lst[start:stop])
            start = stop
            stop += 1
        else:
            stop -= 1
            result.append(lst[start:stop])
            start = stop
            stop += 1

print(result)

Ausgabe:

[[5, 3], [13], [8, 1, 2], [6, 4], [10, 1], [12], [3, 7, 1], [4]]

Aber ich denke, es gibt eine viel intelligentere Lösung für dieses Problem (vielleicht mit Listenverständnis?).

0
xilopaint 24 Feb. 2020 im 00:29

5 Antworten

Beste Antwort

Sie könnten ein Listenverständnis verwenden, aber Sie könnten einfach prüfen, ob die Summe des Hinzufügens des nächsten Elements zur vorherigen Liste den Maximalwert überschreitet. Wenn dies der Fall ist, fügen Sie eine neue Liste hinzu.

result = [[lst.pop(0)]]

for item in lst:
    if sum(result[-1]) + item > max_chunk_sum:
        result.append([item])
    else:
        result[-1].append(item)
4
Sayse 23 Feb. 2020 im 21:49

Dies ist eine typische Arbeit zur Reduzierung ...

from functools import reduce
lst = [5, 3, 13, 8, 1, 2, 6, 4, 10, 1, 12, 3, 7, 1, 4]
init = lst[0:1]
rest = lst[1:]
max_sum = 12
reduce(lambda acc, cur: [*acc[0:-1], [*acc[-1], cur]]
                        if sum(acc[-1]) + cur <= max_sum else
                        [*acc, [cur]],
       rest,
       [init])

PS: Es ist auch eine reine Funktion (unveränderlich) ...

1
godot 25 Feb. 2020 im 14:01

Sie können akkumulieren verwenden, um die laufenden Summen mit Unterbrechungen bei Blocküberschreitungen zu berechnen. Verwenden Sie dann diese Summen, um die Indexbereiche zu bestimmen, die in jede Gruppe aufgenommen werden sollen:

a      = [5, 3, 13, 8, 1, 2, 6, 4, 10, 1, 12, 3, 7, 1, 4]
chunk  = 12

from itertools import accumulate
sums   = accumulate(a,lambda s,v: [s+v,v][s+v>chunk])
breaks = [ i+1 for (i,s),v in zip(enumerate(sums),a[1:]) if s+v>chunk]
groups = [ a[s:e] for s,e in zip([0]+breaks,breaks+[len(a)]) ]

print(groups)
# [[5, 3], [13], [8, 1, 2], [6, 4], [10, 1], [12], [3, 7, 1], [4]]

Wenn Sie nach einer Lösung suchen, ohne Bibliotheken zu verwenden, finden Sie hier eine einfache Schleife, die dies ohne Verwendung von Summe und ohne mehrmaliges Hinzufügen von Werten ausführt:

array  = [5, 3, 13, 8, 1, 2, 6, 4, 10, 1, 12, 3, 7, 1, 4]
chunk  = 12

group,total = [],0
groups      = [group]
for value in array:
    total += value
    if total > chunk:
        group,total = [],value
        groups.append(group)
    group.append(value)

print(groups)

# [[5, 3], [13], [8, 1, 2], [6, 4], [10, 1], [12], [3, 7, 1], [4]]
1
Alain T. 24 Feb. 2020 im 01:39

Ähnlich wie @phoenixo, aber wir können einen Generator verwenden:

def cluster(iterable, max_int):
    start, *iterable = iterable
    cluster = [start]
    for value in iterable:
        if sum(cluster) + value <= max_int:
            cluster.append(value)
        else:
            yield cluster
            cluster = [value]
    yield cluster

Was uns gibt:

In [204]: list(cluster(ints, 12))
Out[204]: [[5, 3], [13], [8, 1, 2], [6, 4], [10, 1], [12], [3, 7, 1], [4]]
1
salt-die 24 Feb. 2020 im 00:16

Hier iteriere ich über lst, verwende eine Unterliste chunk, überprüfe, ob dieser Block> 12 wäre, andernfalls füge ich das neue Element i in chunk hinzu. Wenn es> 12 wäre, füge ich das chunk an result an und erstelle einen neuen Block.

lst = [5, 3, 13, 8, 1, 2, 6, 4, 10, 1, 12, 3, 7, 1, 4]

max_chunk_sum = 12
result = []
chunk = []
for i in lst:
    if sum(chunk) + i <= max_chunk_sum:
        chunk.append(i)
    else:
        if chunk:
            result.append(chunk)
        chunk = [i]
result.append(chunk)
print(result)

Ausgabe :

[[5, 3], [13], [8, 1, 2], [6, 4], [10, 1], [12], [3, 7, 1], [4]]
2
phoenixo 23 Feb. 2020 im 22:19