kleinsten und größten Wert aus Liste von Zahlen ermitteln

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
Unforgiven11
User
Beiträge: 7
Registriert: Donnerstag 10. September 2015, 18:34

Donnerstag 10. September 2015, 18:43

Hallo,

ich arbeite mich gerade durch den Pythonkurs hier: https://open.hpi.de/courses/pythonjunior2014 und stecke bei einer Hausaufgabe dort fest:

Schreibe ein Programm, das die kleinste und die größte Zahl in einer Liste namens Zahlen ausgibt, zum Beispiel in der Form
Die kleinste Zahl ist 10 und die größte Zahl ist 97.
Du musst aber nicht unbedingt einen ganzen Satz ausgeben.
Hinweis: Neben einer Schleife musst Du hier auch if-Anweisungen einsetzen.

Code: Alles auswählen

#Die Zahlenliste ist gegeben
Zahlen = [41, 25, 40, 97, 76, 40, 43, 10]

#Mein Lösungsansatz bisher funktioniert leider nicht:
MINI=0
MAXI=0
j=0
for Zahl in Zahlen:
  if Zahl<Zahlen[j]:
    MINI=Zahl
  elif Zahl>Zahlen[j]:
    MAXI=Zahl
  j=j+1
print("max:",MAXI)
print("min:",MINI)
Kann mir jemand bitte verraten, wie es richtig geht. Es geht nicht darum bei diesem Kurs zu betrügen, der ist eh schon längst abgelaufen. Ich will es nur ernsthaft verstehen lernen und stehe irgendwie auf dem Schlauch...
mutetella
User
Beiträge: 1690
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Donnerstag 10. September 2015, 18:51

@Unforgiven11
Lass Dir doch mal `Zahl` und `Zahlen[j]` ausgeben, dann wirst Du sehen, weshalb.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
kbr
User
Beiträge: 957
Registriert: Mittwoch 15. Oktober 2008, 09:27

Donnerstag 10. September 2015, 19:11

@Unforgiven11: Dein Ansatz ist falsch. Wenn Du die erste Zahl aus Zahlen ausliest, dann setzt Du MINI und MAXI auf diesen Wert. Anschließend vergleichst Du, ob nachfolgende Zahlen größer oder kleiner als MINI und MAXI sind und aktualisierst MINI und MAXI in diesen Fällen dann. (Übrigens kann Python das schon 'eingebaut', aber dann wäre ja die Übung weg.)
Unforgiven11
User
Beiträge: 7
Registriert: Donnerstag 10. September 2015, 18:34

Donnerstag 10. September 2015, 19:16

mutetella hat geschrieben:@Unforgiven11
Lass Dir doch mal `Zahl` und `Zahlen[j]` ausgeben, dann wirst Du sehen, weshalb.

mutetella
Danke für die Antwort.

Okay, also Zahl und Zahlen[j] sind gleich groß.
Ich habe auch schon am Anfang j=1 gesetzt, bekomme dann aber diesen Fehler:

Code: Alles auswählen

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    print(Zahl,Zahlen[j])
IndexError: list index out of range
Logisch, weil ich dann bei der Abarbeitung der Schleife einen Indexwert erreiche, der nicht vorhanden ist. Aber wie umgehe ich das?
Unforgiven11
User
Beiträge: 7
Registriert: Donnerstag 10. September 2015, 18:34

Donnerstag 10. September 2015, 19:22

kbr hat geschrieben:@Unforgiven11: Dein Ansatz ist falsch. Wenn Du die erste Zahl aus Zahlen ausliest, dann setzt Du MINI und MAXI auf diesen Wert. Anschließend vergleichst Du, ob nachfolgende Zahlen größer oder kleiner als MINI und MAXI sind und aktualisierst MINI und MAXI in diesen Fällen dann. (Übrigens kann Python das schon 'eingebaut', aber dann wäre ja die Übung weg.)
Auch für diese Antwort vielen Dank.

Ich glaube, jetzt hab ich es:

Code: Alles auswählen

Zahlen = [191, 978, 357, 11, 13, 993, 904]
MINI=Zahlen[0]
MAXI=Zahlen[0]
for Zahl in Zahlen:
  if Zahl<MINI:
    MINI=Zahl
  elif Zahl>MAXI:
    MAXI=Zahl
print("max:",MAXI)
print("min:",MINI)
  
Oder?
Benutzeravatar
noisefloor
User
Beiträge: 2525
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Donnerstag 10. September 2015, 19:35

Hallo,

die einfachste Lösung ist:

Code: Alles auswählen

>>> zahlen = [1, 9, 6, 5, 3, 4]
>>> min(zahlen)
1
>>> max(zahlen)
9
>>>
Zu Übungszwecken kann man es aber natürlich auch anders machen - aber ich finde so Übungsaufgaben mit mit Absicht viel zu umständlicher Lösung immer suspekt. Zeugt immer von einer gewissen Ideenarmut des Aufgabenstellers.

Gruß, noisefloor
Sirius3
User
Beiträge: 8797
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 10. September 2015, 20:48

@Unforgiven11: Du solltest Dich von Anfang an an ein paar Konventionen halten, Variablen werden komplett klein geschrieben, nur Konstanten werden komplett groß geschrieben. Eingerückt wird pro Ebene mit 4 Leerzeichen und um Operatoren und nach Kommas gehören Leerzeichen. Variablennamen sollten aussagekräftig und nicht abgekürzt werden (minimum, maximum). Das verbessert die Lesbarkeit und erleichtert Dir, Dich auch in Großen Programmen zurechtzufinden.
jerch
User
Beiträge: 1630
Registriert: Mittwoch 4. März 2009, 14:19

Donnerstag 10. September 2015, 20:53

@noisefloor:
Wahrscheinlich will der Aufgabensteller sehen, dass die Aufgabe "zu Fuss" gelöst wurde bzw. den Weg dorthin selbst implementiert.

Ich glaube es braucht einfach eine Weile bis auch Lehrer kapieren, dass grafische Taschenrechner nicht der Untergang des Matheabiturs sind - zu unserer Zeit waren die noch verboten, weil man ja nichts mehr selbst rechnen musste, so die Begründung.
BlackJack

Donnerstag 10. September 2015, 21:16

Alternative zur einfachsten Lösung (von noisefloor) die die Liste mit den Zahlen nur einmal durchgeht:

Code: Alles auswählen

In [4]: zahlen = [1, 9, 6, 5, 3, 4]

In [5]: reduce(lambda (a, b), x: (min(a, x), max(b, x)), zahlen, (zahlen[0], zahlen[0]))
Out[5]: (1, 9)
nezzcarth
User
Beiträge: 586
Registriert: Samstag 16. April 2011, 12:47

Donnerstag 10. September 2015, 21:19

jerch hat geschrieben:@noisefloor:
Wahrscheinlich will der Aufgabensteller sehen, dass die Aufgabe "zu Fuss" gelöst wurde bzw. den Weg dorthin selbst implementiert.
Hinzu kommt vielleicht, dass es für den Speziallfall, dass man, wie hier, das Minimum und das Maximum gleichzeitig bestimmen möchte, noch Optimierungen gibt, die, so wie ich das verstanden habe, theoretisch schneller wären, als separate min()/max() Aufrufe -- praktisch in Python aber natürlich nicht. In einer Prüfungsaufgabe, könnte man für so eine Lösung, die nur "zu Fuß" möglich ist, noch ein paar Extrapunkte locker machen ;)
Benutzeravatar
snafu
User
Beiträge: 5632
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Freitag 11. September 2015, 12:19

Die `reduce`-Lösung führt unter Python 3 zu einem `SyntaxError`. Offenbar mag `lambda` dort keine Tupel-Argumente in der Signatur.

Eine Lösung, die unter Python 2 und Python 3 funktionert:

Code: Alles auswählen

from functools import reduce

def get_minmax(values):
    return reduce(
        lambda mm, v: (min(v, mm[0]), max(v, mm[1])),
        values,
        (values[0],) * 2
    )

def main():
    zahlen = [1, 9, 6, 5, 3, 4]
    print(get_minmax(zahlen))


if __name__ == '__main__':
    main()
Ich würde hier aber eine ausformulierte Python-Schleife, die in das Minimum und Maximum in einem Schritt berechnet, bevorzugen. Es ist lesbarer und (mindestens in CPython) vermutlich auch etwas performanter als die `reduce`-Variante.

EDIT: `timeit` zeigt, dass die `for`-Schleife sogar deutlich schneller abgearbeitet wird. Grundlage für den Vergleich waren die oben gezeigte Funktion sowie:

Code: Alles auswählen

def get_minmax2(values):
    minimum = maximum = values[0]
    for value in values:
        if value < minimum:
            minimum = value
        elif value > maximum:
            maximum = value
    return minimum, maximum
Noch schneller ist es, eigentlich schon erwartungsgemäß, das naheliegende ``minmax = min(zahlen), max(zahlen)`` zu benutzen. Wobei sich die `get_minmax2()`-Funktion im Vergleich dazu noch recht gut schlägt.
shcol (Repo | Doc | PyPi)
Sirius3
User
Beiträge: 8797
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 11. September 2015, 13:01

Der Vorteil der reduce-Lösung ist, dass man irgendeinen Iterator als Parameter übergeben kann.
Die bevorzugte Lösung wäre dann:

Code: Alles auswählen

def minmax(iterable):
    iterable = iter(iterable)
    try:
        minimum = maximum = next(iterable)
    except StopIteration:
        raise ValueError("minmax() arg is an empty sequence")
    for value in iterable:
        if value < minimum:
            minimum = value
        elif value > maximum:
            maximum = value
    return minimum, maximum
Benutzeravatar
snafu
User
Beiträge: 5632
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Freitag 11. September 2015, 13:12

Raymond Hettinger hatte mal ein Snippet ins Netz gestellt, um die Anzahl der Vergleiche zu reduzieren:

Code: Alles auswählen

import itertools

def minmax(data):
    'Computes the minimum and maximum values in one-pass using only 1.5*len(data) comparisons'
    it = iter(data)
    try:
        lo = hi = next(it)
    except StopIteration:
        raise ValueError('minmax() arg is an empty sequence')
    for x, y in itertools.izip_longest(it, it, fillvalue=lo):
        if x > y:
            x, y = y, x
        if x < lo:
            lo = x
        if y > hi:
            hi = y
    return lo, hi

if __name__ == '__main__':
    import random
    data = [random.random() for i in range(1000)]
    print minmax(data)
Quelle: http://code.activestate.com/recipes/577 ... -function/

Dies spielt seine Stärken vor allem dann aus, wenn die Vergleiche relativ zeitaufwändig sind, also z.B. bei String-Vergleichen.
shcol (Repo | Doc | PyPi)
Wolfgang_Amadeus
User
Beiträge: 1
Registriert: Donnerstag 19. Juli 2018, 11:12

Donnerstag 19. Juli 2018, 11:18

for Position in Zahlen:
n=0
if Zahlen[n]>Zahlen[n+1]:
print (Zahlen[n])
else:
print (Zahlen[n+1])
Benutzeravatar
__blackjack__
User
Beiträge: 1571
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 19. Juli 2018, 11:37

@Wolfgang_Amadeus: Das hast Du jetzt aber nicht getestet. Das gibt ja nun offensichtlich nicht das gewünschte Ergebnis aus.

`Position` ist zudem ein falscher Name denn der Wert steht nicht für eine Position. `Position` wird auch nirgends verwendet. `n` wird nie verändert, es wird also `len(Zahlen)` mal der selbe Wert ausgegeben. Entweder das erste oder das zweite Element von `Zahlen`. Vorausgesetzt es gibt dort mindestens zwei Elemente ­— andernfalls gibt es eine Ausnahme.

Code: Alles auswählen

    **** COMMODORE 64 BASIC V2 ****
 64K RAM SYSTEM  38911 BASIC BYTES FREE
   CYBERPUNX RETRO REPLAY 64KB - 3.8P
READY.
█
Antworten