Größter Wert aus Spalte ausgeben

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.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,

bin noch am Anfang, Python 3 zu erlernen.

Ich habe eine Datei, die aus 3 Spalten besteht.
Spalte 1 ist die Hauptgruppennummer, die von 1 bis 20 geht.
Spalte 2 sind zu Spalte 1 dazugehörige Untergruppen.
Spalte 3 beninhaltet eine fortlaufende Nummer und ist abhängig zu Spalte 1 und Spalte 2.

Ich poste hier mal einen kleinen Ausschnitt aus der Datei, damit Ihr Euch das besser vorstellen könnt.
  • 1 FAXGERÄTE-ZUBEHÖR 1
    1 KOPIERER-ZUBEHÖR 2
    1 LASERDRUCKER-ZUBEHÖR 3
    10 BAUMSCHMUCK 1
    10 BRIEF&PAKETWAAGEN 2
    10 BRIEFKARTEN 3
    10 BUCHBOX-VERSANDTASCHEN 4
    10 DATENTRÄGER-VERSAND 5
    10 DEKORATIONEN 6
    10 EINKAUFSKÖRBE 7
    10 EISBLUMEN-SPRAY 8
    10 FLORISTIK 9
    11 SCHEREN 1
    11 TECHNISCHES-ZEICHENPAPIER 2
    11 TINTE&TUSCHE-IM-GLAS 3
    11 TUSCHEFÜLLER&ZUBEHÖR 4
    11 ZEICHENPLATTEN&ZUBEHÖR 5
    11 ZIRKEL&ZIRKELMINEN 6
    12 AQUARELL-FARBKÄSTEN 1
    12 AQUARELL-KREIDEN 2
    12 AQUARELL-PINSELSTIFTE 3
    12 AQUARELL-STIFTE 4
    12 BLEISTIFTE 5
    12 CD-/DVD-MARKER 6
    2 BRIEFUMSCHLÄGE 1
    2 DESIGN-FOLIEN 2
    2 ELEFANTENHAUT 3
    2 ENDLOS-ETIKETTEN 4
    2 ETIKETTEN-ABLÖSER 5
    2 ETIKETTEN-FÜR-DRUCKMASCHINEN 6
    2 FARBLASERDRUCKER-PAPIERE 7
    2 FOLIEN-ETIKETTEN 8
    2 FOTO-PAPIERE 9
    2 KASSEN-/ADDITIONSROLLEN 10
    2 KOPIER-PAPIERE 11
Nun suche ich eine Möglichkeit, den letzten (größten) Wert aus Spalte 3 zu ermitteln.

Beispiel:
Spalte 1: Hauptgruppennummer = 2
Spalte3: Maxwert = 11

Wie kann ich das bewerkstelligen?

Grüße Nobuddy
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Nobuddy hat geschrieben:Beispiel:
Spalte 1: Hauptgruppennummer = 2
Spalte3: Maxwert = 11

Wie kann ich das bewerkstelligen?
Oh, eine Datenbank für Arme. :) So etwas liest man gerne mit dem CSV-Modul aus.

Ich kann jetzt nicht absehen, in welche Richtung die Frage möglicherweise noch zielt, da ich nicht weiß, wie weit "am Anfang" du mit Python 3 bist.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Du kannst die Spalten deines Datensatzes einlesen, indem du das `csv`-Modul einsetzt:

Code: Alles auswählen

import csv

with open('datensatz.csv') as f:
    table = tuple(csv.reader(f))
Und dann kannst du die Funktion `max` benutzen, um die Spalte zu finden mit der größten Zahl als 3. Element:

Code: Alles auswählen

biggest = max(table, key=lambda x: int(x[2]))
Mit dem Parameter `key` kann man eine Funktion übergeben, die den Wert zurückgibt, der bestimmt, welche die größte Spalte ist. In dem Fall soll als `key` der Wert vom 3. Element gelten. `lambda`s sind eine spezielle Art von Funktionen, die nach dem „Lambda-Kalkül“ definiert werden.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Hallo nomnom,

habe das mal so übernommen

Code: Alles auswählen

import csv

with open(uigruppen_path) as f:
    table = tuple(csv.reader(f))

biggest = max(table, key=lambda x: int(x[2]))

print(biggest)
Was folgende Meldung ausgibt:
Traceback (most recent call last): File "b_test.py", line 33, in <module>
biggest = max(table, key=lambda x: int(x[2]))
File "b_test.py", line 33, in <lambda>
biggest = max(table, key=lambda x: int(x[2]))
IndexError: list out of range
Dann habe ich das noch versucht

Code: Alles auswählen

with open(uigruppen_path, 'r') as f:
    table = tuple(csv.reader(f, delimiter="\t"))

for line in table:
    biggest = max(line, key=lambda x: int(x[2]))

    print(biggest)
Was folgende Meldung ausgibt:
Traceback (most recent call last): File "b_test.py", line 33, in <module>
biggest = max(table, key=lambda x: int(x[2]))
File "b_test.py", line 33, in <lambda>
biggest = max(table, key=lambda x: int(x[2]))
ValueError: invalid literal for int() with base 10: '-'
Was läuft falsch, habe ich Dich falsch verstanden?
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Hoppsala, ich habe beim Schreiben vergessen, dass du ja Leerzeichen verwendest für deine Daten. (Denke ich.) Also müsstest du eigentlich als `delimiter` ein Leerzeichen einstellen. `csv.reader(f, delimiter=' ')`.

Edit: Kann es sein, dass dein Datensatz Artikel beinhaltet, die Leerzeichen/Tabs im Titel haben? Werden die Titel nicht mit „Quotes“ (Apostrophen?) eingeschlossen? Das ging aus deinem Beispiel ja nicht hervor. Mein Code + `delimiter`-Parameter funktioniert bei deinem Beispiel sowohl mit Tabs als auch mit Leerzeichen.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

nomnom hat geschrieben:Hoppsala, ich habe beim Schreiben vergessen, dass du ja Leerzeichen verwendest für deine Daten. (Denke ich.) Also müsstest du eigentlich als `delimiter` ein Leerzeichen einstellen. `csv.reader(f, delimiter=' ')`.
Nein, verwende Tabulator (\t) und Leerzeichen gibt es keine.

Habe es jetzt mal zum Laufen gebracht, ohne Fehlermeldung.

Code: Alles auswählen

with open(uigruppen_path, 'r') as f:
    table = tuple(csv.reader(f, delimiter="\t"))

for line in table:
    if line[0] != '---':
        biggest = max(line, key=lambda x: int(line[2]))

        print(biggest)
Leider kommt nich das Ergebnis, was ich mir vorgestellt habe.

Nochmal zurück zu meinem Beisspiel:
18 AKKU-ZAHNBÜRSTEN 1
18 ALLZWECKREINIGER 2
...
..
.
18 TOILETTENPAPIERE&ZUBEHÖR 29
18 WASCHMITTEL 30
18 WC-REINIGER 31
Wie Du hier siehst, hat Spalte 1 hier die Nummer 18.
Die Dritte Spalte zählt wird von der ersten 18 bis zur letzen Zeile numerisch durchgezählt.
Hier sollte dann die erste Spalte mit der dritten Spalte ausgegeben werden.
18 31
So würde ich mir das vorstellen.
Habe dies nur nochmals verdeutlicht, um kein Mißverständnis aufzukommen lassen.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Habe zum obigen Beispiel, das Konstrukt mal angepasst.

Code: Alles auswählen

with open(uigruppen_path, 'r') as f:
    table = tuple(csv.reader(f, delimiter="\t"))

x = 18
for line in table:
    if line[0] == str(x) and line[2] != '---':
        biggest = max(line, key=lambda x: int(line[2]))

        print(biggest)
Was ich dabei aber als Ausgabe erhalte, ist nur die Spalte 1, also hier in diesem Fall die 18 statt der 31.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Von den drei Minussen hast du uns nichts erzählt. Kannst du uns nochmal ein Beispiel aller möglichen Arten von Zeilen geben? Und so, wie du das versuchst, wird das leider garantiert nichts. Denn es macht keinen Sinn, in jeder Zeile nach dem größten Wert zu suchen, indem du immer den Wert der dritten Spalte vergleichst.

Edit: Mit genau diesem Code und diesen Daten funktioniert es. Nur damit du siehst, dass es so eigentlich funktionieren sollte. ;)
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

nomnom hat geschrieben:Von den drei Minussen hast du uns nichts erzählt. Kannst du uns nochmal ein Beispiel aller möglichen Arten von Zeilen geben? Und so, wie du das versuchst, wird das leider garantiert nichts. Denn es macht keinen Sinn, in jeder Zeile nach dem größten Wert zu suchen, indem du immer den Wert der dritten Spalte vergleichst.
Ja, da bin ich auch drauf gekommen ... Schnapsidee.

Hier mal ein kleiner Auschnitt aus der Datei.
--- ZUBEHÖR-FÜR-ANSCHLUSSDOSEN ---
--- ZUBEHÖR-USV-ANLAGEN ---
1 ÖLFARBEN ---
1 FAXGERÄTE-ZUBEHÖR 1
1 KOPIERER-ZUBEHÖR 2
1 LASERDRUCKER-ZUBEHÖR 3
10 BAUMSCHMUCK 1
10 BRIEF&PAKETWAAGEN 2
10 BRIEFKARTEN 3
10 BUCHBOX-VERSANDTASCHEN 4
10 DATENTRÄGER-VERSAND ---
Habe das mit den '---' eingeschränkt.

Code: Alles auswählen

table_list = []

with open(uigruppen_path, 'r') as f:
    reader = csv.reader(f, delimiter="\t")

    for line in reader:
        if line[0] != '---' and line[2] != '---':
            table_list.append(line)
            
table = tuple(table_list)

biggest = max(table, key=lambda x: int(x[2]))

print(biggest)
Jetzt erhalte ich zwar ein richtiges Ergebnis, das aber den max-Wert der dritten Spalte ausgibt, ohne Berücksichtigung von Spalte 1. Also z.B.
Spalte 1 Nummer 1 maxwert 3
Spalte 1 Nummer 2 maxwert 25
Spalte 1 Nummer 3 maxwert 37
... usw.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Wie meinst du das? Als Ergebnis kommt bei mir `['2', 'KOPIER-PAPIERE', '11']`. Ist das nicht, was du möchtest? Die Zeile mit der größten dritten Spalte inklusive Hauptgruppennummer.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

nomnom hat geschrieben:Wie meinst du das? Als Ergebnis kommt bei mir `['2', 'KOPIER-PAPIERE', '11']`. Ist das nicht, was du möchtest? Die Zeile mit der größten dritten Spalte inklusive Hauptgruppennummer.
JEIN, als Gruppierung soll Spalte 1 dienen.
Also von Hauptgruppennummer 1 den Maxwert x,
von Hauptgruppennummer 2 den Maxwert x,
von Hauptgruppennummer 3 den Maxwert x,
von Hauptgruppennummer 4 den Maxwert x,
usw.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Nobuddy hat geschrieben:
nomnom hat geschrieben:Wie meinst du das? Als Ergebnis kommt bei mir `['2', 'KOPIER-PAPIERE', '11']`. Ist das nicht, was du möchtest? Die Zeile mit der größten dritten Spalte inklusive Hauptgruppennummer.
JEIN, als Gruppierung soll Spalte 1 dienen.
Also von Hauptgruppennummer 1 den Maxwert x,
von Hauptgruppennummer 2 den Maxwert x,
von Hauptgruppennummer 3 den Maxwert x,
von Hauptgruppennummer 4 den Maxwert x,
usw.
Achso, ich dachte dein Beispiel in deinem Anfangspost wäre ein komplettes Beispiel gewesen. Dann musst du die Zeilen filtern: Alle Zeilen mit Hauptgruppe 1, 2, 3 etc. Für sowas gibt es die Funktion `filter`.

Code: Alles auswählen

filter(lambda x: int(x[0]) == 1, table) # alle Zeilen aus Hauptgruppe 1
# `table` muss natürlich vorgefiltert sein (es dürfen nicht
# die Zeilen mit den drei Minussen vorhanden sein.
Wobei der erste Parameter von `filter` wiederum eine Funktion ist, die auf jedes Element des im zweiten Parameter festgelegten Iterators (Tupeln, Listen, Wörterbücher, Generatoren) angewandt wird. Also auf jede Zeile. Wenn die Funktion `True` zurückgibt, wird das Element behalten, ansonsten wird das Element eben herausgefiltert.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Hallo nomnnom,

Danke für Deine Hilfe, jetzt funktioniert es! :D

Ich habe das jetzt so umgesetzt:

Code: Alles auswählen

table_list = []
with open(uigruppen_path, 'r') as f:
    reader = csv.reader(f, delimiter="\t")
    for line in reader:
        if line[0] != '---' and line[2] != '---':
            table_list.append(line)
    

erg_list = []
y = 1
while True:
    table = tuple(table_list)
    try:
        biggest = max(filter(lambda x: int(x[0]) == y, table))
        erg_list.append(biggest)
        y = y + 1
    except ValueError:
        break

    print(biggest)
Jetzt wird zu jeder Hauptgruppe der Maximalwert ausgespuckt, genau so wie es sein sollte. :wink:

Grüße Nobuddy
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und nun passe die Namen noch mal an, so dass Du den Datentypen (hier ``list``) nicht im Namen drin stehen hast! Zudem gieße das jetzt endlich mal in Funktionen; beides habe ich Dir auf uu.de schon zig mal "angestrichen" :-D

So, erster "Anschiss" hier im "richtigen" Forum zum Thema ;-)

PS: Ich bin ja erfreut, dass Du Dir meinen Rat zu Herzen genommen und Dich hier angemeldet hast; damit bin ich als Exlusivhelfer ein wenig entlastet :mrgreen:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

Ungetesteter Versuch mit groupby, unter der Annahme, dass alle Untergruppen einer Gruppe direkt hintereinander kommen:

Code: Alles auswählen

from itertools import groupby, itemgetter

with open(uigruppen_path, 'r') as f:
    reader = csv.reader(f, delimiter="\t")
    table = ((int(l[0]), int(l[2])) for l in reader if l[0] != '---')
    groups = (g for k, g in groupby(table, key=itemgetter(0)))
    result = dict(max(g, key=itemgetter(1)) for g in groups)

print(result)
#oder:
print(sorted(result.items()))
(Gibt deine Lösung auch bei mehrstelligen Zahlen das richtige Ergebnis? Stringsortierung und numerische Sortierung sind ja verschieden.)
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammmen,

poste hier mal das komplette Konstrukt, wie ich es jetzt einsetze.

Code: Alles auswählen

table_list = []
erg_list = []
verg_dict = {}
def get_num(filename):
    with open(filename, 'r') as infile:
        reader = csv.reader(infile, delimiter="\t")
        for line in reader:
            if line[0] != '---' and line[2] != '---':
                table_list.append(line)

    y = 1
    while True:
        table = tuple(table_list)
        try:
            biggest = max(filter(lambda x: int(x[0]) == y, table))
            erg_list.append(biggest)
            y = y + 1
        except ValueError:
            break

    for items in erg_list:
        if items[0] != '---':
            verg_dict[items[0]] = items[2]

get_num(subgroupindex_path)


gruppenzaehler_dict = {}
daten_list = []
try:
    with codecs.open(subgroupindex_path, "r") as ziel_file:
        reader = csv.reader(ziel_file, delimiter="\t")
        for line in reader:
            try:
                gruppenzaehler_dict[line[0], line[1]] = line[2]
                a = (line[0], line[1], line[2])
                daten_list.append(a)
            except IndexError:
                pass
except IOError:
    pass

daten_list = sorted(set(daten_list))


zeile_list = []
x = 0
p = 1
for line in daten_list:
    if verg_dict != {}:
        w = verg_dict.get(line[0], line[2])
    else:
        w = ''
    if w == '' and line[0] != '---' and line[2] == '---':
        if line[0] in str(x):
            p = p + 1
            zeile = (line[0], line[1], p)
            zeile_list.append(zeile)
        else:
            p = 1
            zeile = (line[0], line[1], p)
            zeile_list.append(zeile)
            x = x + 1
    else:
        zeile = (line[0], line[1], line[2])
        zeile_list.append(zeile)

zeile_list = sorted(set(zeile_list))

with open(subgroupindex_path, "w") as ziel_file:
    writer = csv.writer(ziel_file, delimiter="\t")
    writer.writerows(zeile_list)
    daten_list = zeile_list

del zeile_list


zeile_list = []
if verg_dict != {}:
   for line in daten_list:
        if line[0] != '---' and line[2] == '---':
            p = verg_dict.get(line[0], line[2])
            p = int(p) + 1
            zeile = (line[0], line[1], p)
            zeile_list.append(zeile)
            get_num(subgroupindex_path)
        else:
            zeile = (line[0], line[1], line[2])
            zeile_list.append(zeile)

zeile_list = sorted(set(zeile_list))


try:
    if zeile_list[0] != '':
        with open(subgroupindex_path, "w") as ziel_file:
            writer = csv.writer(ziel_file, delimiter="\t")
            writer.writerows(zeile_list)
except IndexError:
    pass
Bestimmt würdet Ihr das hier wesentlich kürzer fassen, aber ich kann nur meinem Kenntnisstand etwas entsprechend umsetzen. Alles andere ist ein Lernprozess, der nach und nach kommen wird.

Hyperion, dachte mir das schon ... :wink:
Das Konstrukt, habe ich in eine Funktion verpackt, bistimmt geht es auch kürzer, aber für mich übersichtlicher und noch besser erkennbar.
Das mit den Namenszusätzen, wie name_list oder name_dict, ist für mich noch wichtig, um dies besser erkennen zu können.
Oder kann es da Probleme geben?

bords0, werde dies mal testen!

Das ganze Konstrukt, hat folgende Abläufe sicher zu stellen:

Code: Alles auswählen

- existiert die Datei subgroupindex_path nicht
   - anlegen und befüllen der Datei
      - Gruppierung nach Spalte 1 (Hauptgruppen, 1 - 20)
         - fortlaufender Zähler in Spalte 3 (Untergruppenindex) anlegen
         - Ist der Hauptgruppe kein Wert zugeordnet, erhält dieser auch kein Untergruppenindex

- existiert die Datei subgroupindex_path
   - überprüfen neuer Daten
      - Gruppierung nach Spalte 1 (Hauptgruppen, 1 - 20)
         - fortlaufender Zähler in Spalte 3 (Untergruppenindex) anlegen
         - Ist der Hauptgruppe kein Wert zugeordnet, erhält dieser auch kein Untergruppenindex
           - werden nachträglich der Hauptgruppe einen Wert zugewiesen
             - Zuweisung  Zähler fürUntergruppenindex

   - nicht mehr existierende Daten
     - werden aus Datei gelöscht
        - gelöschter Index wird nicht mehr in der betreffenden Hauptgruppe vergeben
BlackJack

@Nobuddy: Das mag syntaktisch eine Funktion sein, aber Funktionen veränder normalerweise keine Datenstrukturen, die nicht als Argumente übergeben wurden. Weil damit das Programm unübersichtlich wird. Man sieht nicht mehr was, wo verändert oder benutzt wird.

Wenn Namen nur innerhalb einer relativ kurzen Funktion verwendet werden, dann brauchst Du auch die Namenszusätze für die Typen nicht. Also mehr Quelltext in Funktionen stecken. Auf Modulebene sollten nur definitionen von Konstanten stehen, also Namen aus importen, Funktions- und Klassendefinitionen, und Namen die an Konstante Werte gebunden sind. Die Typ-Anhängsel bei den Namen werden dann zum Problem, wenn man den Typ ändert. Dann muss man nämlich auch überall denn Namen ändern.

Statt Typen an die Namen anzuhängen, solltest Du lieber Abkürzungen vermeiden. Namen sollen das Verständnis des Quelltextes erleichtern. `verg_dict` tut das für mich nicht. Und für Dich in einem halben Jahr wahrscheinlich auch nicht mehr.

Nochmal zurück zur Funktion: Da werden Daten an eine `table_list` angehängt, und die Funktion wird mehrfach aufgerufen und das anscheinen auch immer mit dem selben Argument. Ausserhalb der Funktion wird der Name `table_list` nicht verwendet. Soll das so sein? Das ist alles sehr verwirrend, und sieht für mich erst einmal falsch aus. Werte sollten Funktionen als Argumente betreten und als Rückgabewerte verlassen. Eine Funktion sollte ausser auf Konstanten auf nichts „einfach so” zugreifen.

Warum wird in `get_num()` ein Tupel aus `table_list` erstellt? Der Schritt ist unnötig.

Statt `filter()` könnte man hier `itertools.ifilter()` verwenden. Beziehungsweise ist das wahrscheinlich in der Form sowieso kaputt, denn das `max()` bezieht sich auf Zeichenketten und nicht auf Zahlen:

Code: Alles auswählen

In [4]: max('7', '42')
Out[4]: '7'
Die Abbruchbedingung für die Verarbeitung ist auch ziemlich undurchsichtig. Das scheint sich darauf zu verlassen, dass am Anfang der `table_list` die Elemente mit Werten sind, und dann noch welche folgen, bei denen zumindest beim ersten Element in der ersten Spalte keine Ziffernfolge steht. Das ist für meinen Geschmack etwas zu implizit und sollte schon beim Einlesen gelöst werden. Die Liste sollte nur Daten enthalten, mit denen man auch etwas anfangen kann.

Jetzt wird mir auch klar warum es nichts ausmacht, dass die Funktion mehrfach aufgerufen wird und `table_list` immer weiter wächst. Es werden trotzdem immer die selben Datensätze am Anfang der Liste verarbeitet und der ganze, immer grösser werdende Rest ignoriert. WTF…

Weiter lese ich in dem Quelltext jetzt mal nicht…
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Hallo BlackJack,

Danke für Deine Kritik!

Ich kann mir vorstellen, daß für Jemand der in der Materie drin ist, Kopfschütteln und vielleicht auch Bauchschmerzen, bei meiner jetzigen Programmierweise bekommt.
Da liegt noch ein langer Weg vor mir, hoffe aber mit Eurer Unterstützung, dies zu schaffen.

Ich werde versuchen, die Kritikpunkte umzusetzen. :wink:

Grüße Nobuddy
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Wäre das eine Funktion, so wie Du sie forderst?

Code: Alles auswählen

def get_write(filename, datenpool):
    with open(filename, "w") as zielfile:
        writer = csv.writer(zielfile, delimiter="\t")
        writer.writerows(datenpool)

get_write(subgroupindex_path, neuedaten)
BlackJack

@Nobuddy: Das wäre eine Funktion die keine Datenstrukturen verwendet, die nicht als Argument herein gekommen sind, ja. Allerdings ist der Name irreführend, denn bei `get_*` erwartet man einen Rückgabewert.
Antworten