Jeden 5-ten Listeneintrag ersetzen

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
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

hallo,
ich hab eine liste, in der ich jeden 5-ten eintrag ersetzen (erneuern) muss.

Code: Alles auswählen

['01.09.2015', '100', '500', '100', '9', '91', '08.09.2015', '15', '45', '14.5', '9', '5.5', '11.09.2015', '1', '1', '1000', '4', '996', '16.09.2015', '15', '45', '8.75', '9', '-0.25', '30.09.2015', '15', '45', '10', '9', '1']
wie geht das?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nun, indem du jedes 5. Element ersetzt:

Code: Alles auswählen

In [1]: xs = ['01.09.2015', '100', '500', '100', '9', '91', '08.09.2015', '15', '45', '14.5', '9', '5.5', '11.09.2015', '1', '1', '1000', '4', '996', '16.09.2015', '15', '45', '8.75', '9', '-0.25', '30.09.2015', '15', '45', '10', '9', '1']

In [2]: ['new' if i % 5 == 0 else x for i, x in enumerate(xs, 1)]
Out[2]: ['01.09.2015',  '100',  '500',  '100', 'new',
             '91', '08.09.2015', '15', '45', 'new',
             '9',  '5.5',  '11.09.2015',  '1',  'new',
             '1000', '4', '996', '16.09.2015', 'new',
             '45', '8.75', '9', '-0.25', 'new',
             '15', '45', '10', '9', 'new']
Aber da du immer ein Datum gefolgt von 5 Werten hast, denke ich dass du erstmal ueber deine Datenstruktur nachdenken solltest. Eine einfache Liste bildet das offensichtlich nicht besonders gut ab.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@DMD: Vermutlich möchtest du nicht jedes fünfte, sondern jedes sechste Element ersetzen, denn deine Struktur scheint sich nach jeweils sechs Elementen zu wiederholen, nicht nach fünf. Das erste zu ersetztende Element ist dann am index 5, welches der sechste Index ist, weil wir bei 0 zu zählen beginnen. Also etwa so:

Code: Alles auswählen

>>> xs = ['01.09.2015', '100', '500', '100', '9', '91', '08.09.2015', '15', '45', '14.5', '9', '5.5', '11.09.2015', '1', '1', '1000', '4', '996', '16.09.2015', '15', '45', '8.75', '9', '-0.25', '30.09.2015', '15', '45', '10', '9', '1']
>>> len(xs)
30
>>> xs[5::6] = ['new'] * 5  # 5 == 30 / 6
>>> xs
['01.09.2015', '100', '500', '100', '9', 'new', '08.09.2015', '15', '45', '14.5', '9', 'new', '11.09.2015', '1', '1', '1000', '4', 'new', '16.09.2015', '15', '45', '8.75', '9', 'new', '30.09.2015', '15', '45', '10', '9', 'new']
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@DMD: Wie schon angedeutet wurde, gibt es in Python eine Slicing-Syntax für Sequenzen (z.B. Listen, Tupel oder Strings), die als ``sequence[start:stop:step]`` definiert ist. "step" gibt dabei an, um wieviele Elemente weitergesprungen werden soll, bevor das nächste Element ausgewählt wird. Jedes dieser Parameter kann dabei ausgelassen werden. Die Einsetzungen beim Weglassen von Parametern lauten: start=0, stop=len(sequence), step=1. Mit diesem Wissen sollte man folgende Beispiele verstehen:

Code: Alles auswählen

>>> 'Hallo Welt!'[0::1]
'Hallo Welt!'
>>> 'Hallo Welt!'[0::2]
'HloWl!'
>>> 'Hallo Welt!'[::2]
'HloWl!'
>>> 'Hallo Welt!'[::3]
'HlWt'
>>> 'Hallo Welt!'[4::3]
'oe!'
Selbst ein Umkehren der Sequenz ist möglich, da man für "step" auch negative Zahlen angeben darf:

Code: Alles auswählen

>>> 'Hallo Welt!'[::-1]
'!tleW ollaH'
>>> 'Hallo Welt!'[::-2]
'!lWolH'
>>> 'Hallo Welt!'[9::-2]
'te la'
Ich setze jetzt mal voraus, dass du dies gedanklich auch auf deinen Datenstruktur übertragen kannst... :)

EDIT: Aber hier nochmal eine Hilfetellung:

Code: Alles auswählen

>>> seq = range(10)
>>> seq
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> seq[::3]
[0, 3, 6, 9]
>>> seq[::3] = [-1] * len(seq[::3])
>>> seq
[-1, 1, 2, -1, 4, 5, -1, 7, 8, -1]
Zugegeben ist das ``len(seq[::3])`` etwas billig und kann bei sehr großen Sequenzen die Ausführungszeit signifikant beeinflussen. In diesem Fall kann man die Anzahl der einzusetzenden Elemente selbst berechnen (Stichwort: `divmod()`).

Wobei ich bei sehr großen Listen wahrscheinlich auch keine Inplace-Einsetzungen mehr machen würde.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD: statt Elemente einer Liste zu ersetzen, solltest Du statt dessen eine neue Liste anlegen, weil so Änderungen sich nur auf die lokale Umgebung auswirken und damit Programme viel übersichtlicher und fehlerfreier werden. Eine Liste sollte nur gleichartige Objekte enthalten, was bei Deiner Liste offensichtlich nicht der Fall ist, sie besteht aus der String-Representation eines Datums und den Stringrepresentationen von 5 Fließkommazahlen. Das ist in mehrererlei Hinsicht nicht optimal. Zum Rechnen sind Stringrepresentationen von Zahlen nicht geeignet, die lineare Liste einer mehrdimensionalen Struktur läßt Dich seltsame Aufgaben lösen, wie z.B. jedes n-te Element zu ersetzen. Das ist nicht nur umständlich, sondern geht spätestens dann schief, wenn aus den 5 Elementen irgendwann einmal 6 werden.
Deine erste Aufgabe wäre also, die Liste in eine sinnvolle Datenablage zu konvertieren. Am besten geschieht das gleich beim Lesen der Daten. Die Rückumwandlung findet dann beim Schreiben in eine Datei statt.

Code: Alles auswählen

import datetime
from collections import namedtuple


class Stockdata(namedtuple('StockData', 'date, whiskey, beer, wine, water, milk')):
    @classmethod
    def from_strings(cls, date, whiskey, beer, wine, water, milk):
        return cls(datetime.datetime.strptime(date, '%d.%m.%Y'),
            float(whiskey), float(beer), float(wine), float(water), float(milk))

data = ['01.09.2015', '100', '500', '100', '9', '91', '08.09.2015', '15', '45', '14.5', '9', '5.5', '11.09.2015', '1', '1', '1000', '4', '996', '16.09.2015', '15', '45', '8.75', '9', '-0.25', '30.09.2015', '15', '45', '10', '9', '1']
stock = map(Stockdata.from_strings, *[iter(data)]*6)

new_stock = [item._replace(milk=item.milk + 5) for item in stock]
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

vielen dank für eure mühen.
sehr hilfreich für mich :)
THX
Antworten