Seite 1 von 1

Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 15:18
von Chrisseeey
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

Re: Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 15:48
von __blackjack__
@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.

Re: Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 18:20
von mechanicalStore
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.

Re: Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 19:31
von Sirius3
`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())

Re: Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 19:49
von __blackjack__
@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. 😇

Re: Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 20:36
von ThomasL
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())]

Re: Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 20:42
von narpfel
Warum gibt es das, aber nicht UUOK (useless use of `keys`) und UUOR (useless use of `readlines`) für Python? :mrgreen:

Re: Dictionaries

Verfasst: Donnerstag 9. Juni 2022, 20:47
von __blackjack__
@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()

Re: Dictionaries

Verfasst: Freitag 10. Juni 2022, 08:03
von ThomasL
@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)]