Dictionaries

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Chrisseeey
User
Beiträge: 7
Registriert: Donnerstag 9. Juni 2022, 15:02

Hallo Liebe Alle!

Ich habe folgendes Problem:

Für meinen Python Kurs in der Uni muss ich eine Übung zu dictionaries machen.

Wir haben folgendes dict gegeben:

cities = {'Berlin': [52.517277, 13.406632, 15], 'Muenchen': [48.139742, 11.574174, 10], 'Koeln': [50.943272, 6.958354, 9]}

wobei die values also die liste jeweils für den breitengrad, längengrad und die stadtgöße in km angegeben sind.

Wir sollen nun eine Funktion schreiben, die das dict übergeben bekommt und in alphabetischer Reihenfolge ein Tupel aus Namen und den Koordinates des Zentrums in einer Liste zurück gibt. Das soll dann so aussehen:
[("Berlin", 52.517277, 13.406632), ("Koeln", 50.943272, 6.958354), ("Muenchen", 48.139742, 11.574174)]

Ich habe angefangen folgende Funktion zu schreiben:

def alphabetic_list(cities):
result = list(sorted(cities.items()))
return result

alphabetic_list(cities)

Bei dieser krieg ich eben nur leider kein tuple und das dritte element von den values sollte da auch nicht sein.

Ich wäre über jede Hilfe und jeden Tipp sehr dankbar!

Viele Grüße

Chrissi
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Chrisseeey: `items()` liefert halt nicht das was Du brauchst, also musst Du Code schreiben der ein einzelnes Element von `items()` entsprechend umformt. Du bekommst ein Tupel mit zwei Elementen und das zweite Element ist eine Liste mit drei Elementen. Daraus musst Du ein Tupel mit dem ersten Element aus dem Items-Tupel und den beiden ersten Elementen aus der Liste machen. Vielleicht erst einmal ausführlich mit einer Schleife über die Elemente die `items()` liefert. Wenn das funktioniert, kannst Du immer noch versuchen das kompakter zu schreiben mit `sorted()` und einem Generatorausdruck.

Der `list()`-Aufruf ist übrigens zu viel. `sorted()` liefert bereits eine neue, sortierte Liste.

Funktionsnamen beschreiben üblicherweise die Tätigkeit, welche die Funktion durchführt, um sie von eher passiven Werten unterscheiden zu können. `alphabetic_list` ist keine Tätigkeit.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
mechanicalStore
User
Beiträge: 179
Registriert: Dienstag 29. Dezember 2009, 00:09

Aus eigener (un)Erfahrung kann ich nur den Rat geben, ein (oder mehrere) Wochenende(n) hierin zu investieren:

https://www.amazon.de/Quick-Python-Book ... C78&sr=8-1

Auch wenn hier keine Lösungen präsentiert werden sollen, hier eine der Möglichkeiten, aus eigenem Interesse zu Lernzwecken und um auch mal was beizutragen:

Code: Alles auswählen

def convert_to_sorted_list_without_town_width(cities):
    
    # unoptimized
    # keys = []
    # for b in cities.keys():
    #    keys.append(b)
    # keys.sort()

    # optimized
    keys = sorted([key for key in cities.keys()])

    # unoptimized
    # result = []
    # for c in keys:
    #    result.append(tuple([ c, cities[c][0], cities[c][1] ])
    #    )

    # optimized
    result = [ tuple( [ c, cities[c][0], cities[c][1] ] ) for c in keys ]

    return result

def main():
    cities = {'Berlin': [52.517277, 13.406632, 15], 'Muenchen': [48.139742, 11.574174, 10], 'Koeln': [50.943272, 6.958354, 9]}
    print(convert_to_sorted_list_without_town_width(cities))

if __name__ == '__main__':
    main()
Das geht aber sicherlich noch kompakter.
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

`sorted` erwartet ein iterierbares Objekt, was `cities.keys()`, bzw. `cities` bereits liefert, eine List-Comprehension ist dort unnötig, und in der Form auch besser als `list(cities)` zu schreiben.
Ein `Tuple` erzeugt man einfach, indem man mehrere Werte per Komma trennt, es ist also nicht nötig, erst eine Liste zu erzeugen.
Eine List-Comprehension ist auch keine "Optimierung" sondern nur eine kompaktere Schreibweise.

Code: Alles auswählen

def convert_to_sorted_list_without_town_width(cities):
    keys = sorted(cities)
    return [(c, cities[c][0], cities[c][1]) for c in keys]
Jetzt sind die magischen Indizes, und der doppelte Zugriff auf das Wörterbuch noch unschön, besser wäre es, per Unpacking die Werte gleich in sprechende Namen umzuwandeln.

Code: Alles auswählen

def convert_to_sorted_list_without_town_width(cities):
    return sorted((name, latitude, longitude)
        for name, (latitude, longitude, _town_width) in cities.items())
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@mechanicalStore: Es werden zu viele Listen erstellt. Und einige zu umständlich.

Mal das erstellen von `keys` in mehreren Schritten vereinfacht (`b` war ein sehr schlechter Name für einen Städtenamen):

Code: Alles auswählen

    names = []
    for name in cities.keys():
        names.append(name)
    names.sort()

    # =>
    
    names = []
    for name in cities:
        names.append(name)
    names.sort()
    
    # => 
        
    names = list(cities)
    names.sort()

    # =>
    
    names = sorted(cities)
Beim zweiten Schritt ist es unsinnig erst eine Liste zu erstellen und die dann mit `tuple()` in ein Tupel zu kopieren, statt einfach gleich ein Tupel zu erstellen:

Code: Alles auswählen

    result = []
    for name in names:
        result.append(tuple([name, cities[name][0], cities[name][1]]))

    # =>

    result = []
    for name in names:
        result.append((name, cities[name][0], cities[name][1]))

    # =>

    result = []
    for name in names:
        latitude, longitude, _size = cities[name]
        result.append((name, latitude, longitude))
Der letzte Umformungsschritt dient der Lesbarkeit um die magischen Indexzugriffe los zu werden.

Ungünstig ist hier das Du die Daten trennst. Man muss ja nicht die Namen sortieren, sondern kann auch Tupel nach Namen sortieren, was besonders einfach ist, wenn der Name das erste Element im Tupel ist. Wenn man von dem ausgeht was die `items()`-Methode liefert, kommt man mit einem einzigen Ausdruck aus. Der erstaunlicherweise sogar lesbar ist. Man braucht nur `sorted()` einen Generatorausdruck, und die `items()`-Methode.

Und ich sehe Sirius3 war schneller. 😇
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
ThomasL
User
Beiträge: 1379
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Meine Lösung sieht so aus:

Code: Alles auswählen

def convert_to_sorted_list_without_town_width(cities):
    return [(town, *cities[town][:2]) for town in sorted(cities.keys())]
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
narpfel
User
Beiträge: 691
Registriert: Freitag 20. Oktober 2017, 16:10

Warum gibt es das, aber nicht UUOK (useless use of `keys`) und UUOR (useless use of `readlines`) für Python? :mrgreen:
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@narpfel: Berechtigte Frage! 😀

@all: Nur mal spasseshalber eine Lösung mit `glom`:

Code: Alles auswählen

#!/usr/bin/env python3
from pprint import pprint

from glom import Invoke, Iter, T, glom

Tuple = Invoke(lambda *args: tuple(args)).specs


def get_sorted_names_and_coordinates(name_to_data):
    return glom(
        name_to_data,
        (T.items(), Iter(Tuple("0", "1.0", "1.1")), sorted),
    )


def main():
    cities = {
        "Berlin": [52.517277, 13.406632, 15],
        "Muenchen": [48.139742, 11.574174, 10],
        "Koeln": [50.943272, 6.958354, 9],
    }
    pprint(get_sorted_names_and_coordinates(cities))


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
ThomasL
User
Beiträge: 1379
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

@narpfel ja, ich habe den Wink mit dem Zaunpfahl verstanden. Ich nehme dies als gezwinkerte konstruktive Kritik wohlwollend zur Kenntnis und lerne daraus.

Code: Alles auswählen

def convert_to_sorted_list_without_town_width(cities):
    return [(town, *cities[town][:2]) for town in sorted(cities)]
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Antworten