Toon posts:

Python & geneste lijsten

Pagina: 1
Acties:

Vraag


  • utopiaBe
  • Registratie: Maart 2009
  • Niet online
Mijn vraag
Ik ben grandioos de mist aan het ingaan met geneste lijsten en als beginner kom ik er niet uit.

Wat ik zou moeten bekomen is het gemiddelde van het j-de element uit de sublijsten (die niet even lang moeten zijn.

listAvgs([[1,2,3],[4,5],[6,7,8,9],[10]]) zou dan het resultaat van [(1+4+6+10)/4, (2+5+7)/3, (3+8)/2, 9/1] moeten geven, of [5.25,4.67,5.5,9.0]

Ik zit me echter blind te staren op wat ik heb en kan er maar niet doorheen kijken. Mijn opzet was:
1) sla de lengtes van elke rij op in lijst
2) vul vervolgens elke kolom aan met 0 waar niks staat (neutraal element kan dan mee in som)
3) nu kan je de som nemen over elke rij en dit opslaan in een lijst
4) loop over som en lengtes om tot je gemiddelden te komen

So far, so good... ware het niet dat ik op 1 vastloop. De lengte van de kolommen is niet complex, ik zie echter niet hoe je die van de rijen kan bekomen.

Transpose zou een noodoplossing zijn, ware het niet dat numpy in de hele cursus niet aan bod komt en dit dus zeker niet de bedoeling is. Dit is overigens geen taak. Ik probeer me door wat oefeningen te worstelen voor een aankomend examen.
...

Relevante software en hardware die ik gebruik:
Python 3.10.5 in Wing
...

Wat ik al gevonden of geprobeerd heb:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def listAvgs(lst):
    longest = longestSublist(lst) #deze functie geeft de lengte van de langste sublijst weer
    lengths = []
    sums = []
    total = 0
    #selecteer lengte voor alle RIJEN (nu dus kolommen)
    for row in lst:
        lengths.append(len(row))
    #Wanneer rijen niet zo lang zijn als langste sublijst -> vul aan met neutraal element voor som
    for i in range(0,len(lst)):
        while len(lst[i])<longest:
            lst[i].append(0)
    #Neem som van i-de element in rij 
    for i in range(0,len(lst)):
        for j in range(0,longest):
            total += lst[j][i]
        sums.append(total)
        total = 0
    print('sums: ', sums)
    print('lengths: ', lengths)
    for i in range(0,len(lengths)):
        sums[i] = sums[i]/lengths[i]
    return sums

print(listAvgs([[1,2,3],[4,5],[6,7,8,9],[10]]))

...

Alle reacties


  • thlst
  • Registratie: Januari 2016
  • Niet online
Aanvullen lijkt me geen goed idee.

Waarschijnlijk wil je bij deze opdracht Exceptions gebruiken. Zijn deze al behandeld?

  • utopiaBe
  • Registratie: Maart 2009
  • Niet online
Nee, is echt nog de basis. Exceptions dus nog niet gezien. Eigenlijk enkel de basisbewerkingen, functies, lijsten, tuples, strings & sets (geen numpy, zip, etc. dus). Het is net dat wat het geheel wat complexer maakt dan nodig... Vandaar ook dat ik aan dat aanvullen dacht. Loop je natuurlijk nog steeds aan tegen het feit dat je de lengte van de rijen niet zonder meer kan opvragen.

Wellicht is er dus een erg eenvoudige oplossing en zit ik me gewoon blind te staren op 'wat ik wel zou kunnen toepassen, maar niet mag'.

[Voor 44% gewijzigd door utopiaBe op 30-12-2022 05:13]


  • Wolfboy
  • Registratie: Januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

Ik neem aan dat je nog geen libraries zoals collections enzo behandeld hebt dus we gaan het even zo eenvoudig mogelijk maken :)

Door iets meer in de loop te doen hoef je niet eerst de langste sublijst te vinden:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def listAvgs(lst):
    # Verzamel de totale som en de lengtes in deze lijsten
    totals = []
    lengths = []

    for sublist in lst:
        # Loop door de sublijst met een counter. Als je `enumerate` niet mag
        # gebruiken dan kan je ook gewoon een `i += 1` in de loop zetten
        for i, value in enumerate(sublist):
            # Als we nog geen lijst van lengte `i` gehad hebben
            if i >= len(totals):
                totals.append(0)
                lengths.append(0)

            totals[i] += value
            lengths[i] += 1

    # Bereken het gemiddelde voor alle getallen
    results = []
    for total, length in zip(totals, lengths):
        results.append(total / length)

    return results

print(listAvgs([[1,2,3],[4,5],[6,7,8,9],[10]]))


Maar we kunnen het natuurlijk ook omgekeerd doen door eerst door de sublijsten heen te lopen:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def listAvgs(lst):
    # Maak een lijst voor de resultaten
    results = []

    # Loop van 0 tot we geen langere lijsten meer kunnen vinden
    i = 0
    while True:
        total = 0
        count = 0

        for sublist in lst:
            # Als de lijst lang genoeg is, voeg het getal dan toe aan `total`
            if len(sublist) > i:
                total += sublist[i]
                count += 1

        # Als er waarden zijn, voeg ze dan toe aan de resultaten. Als die er
        # niet zijn dan moeten we uit de loop springen zodat we niet oneindig
        # loopen.
        if count:
            results.append(total / count)
        else:
            break

        i += 1

    return results

print(listAvgs([[1,2,3],[4,5],[6,7,8,9],[10]]))

Blog [Stackoverflow] [LinkedIn]


  • Ben(V)
  • Registratie: December 2013
  • Laatst online: 22:25
Waarom zo ingewikkeld, python heeft daar de functies sum() en len() voor.
Zoiets dus:

code:
1
2
3
4
LongList = [[1,2,3],[4,5],[6,7,8,9],[10]]

for Sublist in LongList:
    print(sum(Sublist)/len(Sublist))

[Voor 5% gewijzigd door Ben(V) op 30-12-2022 09:44]

All truth passes through three stages: First it is ridiculed, second it is violently opposed and third it is accepted as being self-evident.


  • MaNDaRK
  • Registratie: Oktober 2001
  • Laatst online: 22:43
[quote]Ben(V) schreef op vrijdag 30 december 2022 @ 09:42:
Waarom zo ingewikkeld, python heeft daar de functies sum() en len() voor.
Zoiets dus:

[code]
LongList = [[1,2,3],[4,5],[6,7,8,9],[10]]

for Sublist in LongList:
print(sum(Sublist)/len(Sublist))
[/code]
[/quote]
Dit is inderdaad een mooie oplossing.

Of moet de ts alles zelf uitrekenen met geneste loops?
beter lezen.

  • eheijnen
  • Registratie: Juli 2008
  • Niet online
@Ben(V), @MaNDaRK
Vind de uitleg van @Wolfboy eigenlijk juist goed en helemaal niet overbodig.

Kan TS eens zien hoe en waarom het werkt. En deze uitleg kan in andere scenarios nog wel eens van pas komen...

En snapt hij ook meteen hoe de SUM functie werkt die BenV demonstreert.
Ook een een goed voorbeeld trouwens om te laten zien hoe het compacter kan in dit geval.

The Internet connected people all around the world. But also the Village Idiots...


  • Wolfboy
  • Registratie: Januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

Ben(V) schreef op vrijdag 30 december 2022 @ 09:42:
Waarom zo ingewikkeld, python heeft daar de functies sum() en len() voor.
Zoiets dus:

code:
1
2
3
4
LongList = [[1,2,3],[4,5],[6,7,8,9],[10]]

for Sublist in LongList:
    print(sum(Sublist)/len(Sublist))
Die klopt alleen totaal niet :P
Het gaat om de som van de getransponeerde versies van de sublijsten.

Blog [Stackoverflow] [LinkedIn]


  • utopiaBe
  • Registratie: Maart 2009
  • Niet online
@Wolfboy: dankjewel! Dit verheldert inderdaad een hoop. Ook de 2 uitwerkingen naast mekaar...
Was duidelijk weer te ver aan het zoeken. Enumerate & zip was effectief nog niet gezien, maar kan me daar nu geen issue bij voorstellen. Bedoeling was vooral dat we geen collections, numpy, pandas,... gingen gebruiken.

@Ben(V) : thanks. Een esthetische oplossing, maar zoals hierboven gezegd neem je dan het gemiddelde van de lijsten (wat het probleem een stuk eenvoudiger maakt natuurlijk). Dat was waar ik wat op vast liep, aangezien deze sublists niet van gelijke lengte waren.

  • eheijnen
  • Registratie: Juli 2008
  • Niet online
Als je nog wat tijd over hebt dit weekend...een beetje leesvoer over "jagged arrays".
Wikipedia: Jagged array

The Internet connected people all around the world. But also the Village Idiots...


  • Ben(V)
  • Registratie: December 2013
  • Laatst online: 22:25
Sorry mijn fout , dat krijg je als je te snel over de vraag heen leest.
Hier dan een compacte versie die wel goed is voor de fun

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from itertools import zip_longest

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

# Compact
ListOfSums = [sum(ListToSum)/len(ListToSum) for ListToSum in [list(filter(None, transposed)) for transposed in zip_longest(*LongList)]] 
print(ListOfSums )

[# hetzelfde maar uitgesplitst
# eerst transponeer je de list of lists
transposed  = list(zip_longest(*LongList))
# Dat resulteerd in "None' waarden in de list, dus die moeten eruit, dat doe je met een filter
print (transposed)

# Dan halen we met een filter die "None" waarden eruit.
NoneRemoved = [list(filter(None, item)) for item in transposed]
print(NoneRemoved )

# En tenslotte maken we met sum() en len() een list van de gewesnte waarden
ListOfSums  = [sum(ListToSum)/len(ListToSum) for ListToSum in NoneRemoved]
print(ListOfSums)

[Voor 22% gewijzigd door Ben(V) op 30-12-2022 17:42]

All truth passes through three stages: First it is ridiculed, second it is violently opposed and third it is accepted as being self-evident.


  • MaNDaRK
  • Registratie: Oktober 2001
  • Laatst online: 22:43
Wolfboy schreef op vrijdag 30 december 2022 @ 11:58:
[...]
Die klopt alleen totaal niet :P
Het gaat om de som van de getransponeerde versies van de sublijsten.
Je hebt helemaal gelijk! Het gaat om alle 'nth' nummers van de lijsten.

Dan heb ik hier een iets uitgebreidere versie, natuurlijk niet waterdicht als je lijst nullen bevat.
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# orginele lijst
long_list = [[1, 2, 3], [4, 5], [6, 7, 8, 9], [10]]

# variabele voor de langste lijst:
longest = 0

# variabele voor de lijst lengte:
list_length = []

# variabele voor de resultaten:
result = []

# check welke sub_list het langste is:
for sub_list in long_list:
    if longest < len(sub_list):
        longest = len(sub_list)

# longest heeft nu de langste lijst:
# print(longest)

# sub_list eventueel aanvullen:
for sub_list in long_list:
    if len(sub_list) < longest:
        for _ in range(longest - len(sub_list)):
            sub_list.append(0)

# long_list heeft nu allemaal dezelfde lijst lengtes
# print(long_list)

# alles bij elkaar optellen:
for c in range(longest):
    temp = 0
    ll = 0
    for x in range(len(long_list)):
        # dit is natuurlijk niet waterdicht
        if long_list[x][c] != 0:
            ll += 1
        temp += long_list[x][c]
    
    # lijst lengte aanvullen:
    list_length.append(ll)
    
    # resultaat aanvullen:
    result.append(temp)

# berekenen resultaten:
for c in range(len(result)):
    result[c] = result[c] / list_length[c]

print(result)

  • utopiaBe
  • Registratie: Maart 2009
  • Niet online
Zo, en ik twijfelde nog om deze vraag initieel op het forum te gooien. Veel bijgeleerd, ook van de oplossingen die zaken gebruiken die ik nog niet zag (ondertussen ken ik die dan ook). Prachtig dit.

@eheijnen die jagged lists verken ik iig dieper. Met wat extra oefenen krijg ik dit wel onder de knie ;-). Door omstandigheden wat lessen moeten missen, maar uiteindelijk is het een kwestie van oefenen natuurlijk. Loopt ook vrij vlot, behalve deze dus...
Pagina: 1


Tweakers maakt gebruik van cookies

Tweakers plaatst functionele en analytische cookies voor het functioneren van de website en het verbeteren van de website-ervaring. Deze cookies zijn noodzakelijk. Om op Tweakers relevantere advertenties te tonen en om ingesloten content van derden te tonen (bijvoorbeeld video's), vragen we je toestemming. Via ingesloten content kunnen derde partijen diensten leveren en verbeteren, bezoekersstatistieken bijhouden, gepersonaliseerde content tonen, gerichte advertenties tonen en gebruikersprofielen opbouwen. Hiervoor worden apparaatgegevens, IP-adres, geolocatie en surfgedrag vastgelegd.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Toestemming beheren

Hieronder kun je per doeleinde of partij toestemming geven of intrekken. Meer informatie vind je in ons cookiebeleid.

Functioneel en analytisch

Deze cookies zijn noodzakelijk voor het functioneren van de website en het verbeteren van de website-ervaring. Klik op het informatie-icoon voor meer informatie. Meer details

janee

    Relevantere advertenties

    Dit beperkt het aantal keer dat dezelfde advertentie getoond wordt (frequency capping) en maakt het mogelijk om binnen Tweakers contextuele advertenties te tonen op basis van pagina's die je hebt bezocht. Meer details

    Tweakers genereert een willekeurige unieke code als identifier. Deze data wordt niet gedeeld met adverteerders of andere derde partijen en je kunt niet buiten Tweakers gevolgd worden. Indien je bent ingelogd, wordt deze identifier gekoppeld aan je account. Indien je niet bent ingelogd, wordt deze identifier gekoppeld aan je sessie die maximaal 4 maanden actief blijft. Je kunt deze toestemming te allen tijde intrekken.

    Ingesloten content van derden

    Deze cookies kunnen door derde partijen geplaatst worden via ingesloten content. Klik op het informatie-icoon voor meer informatie over de verwerkingsdoeleinden. Meer details

    janee