Items der List nach der Reihe durchgehen

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
VoLLioMenTT
User
Beiträge: 21
Registriert: Montag 16. Oktober 2017, 16:00

Liebe Python-Forum Community,

Ich schreibe gerade ein Programm, dass aus der 1. Excel Datei Strings ausließt, nach diesen dann in der 2. Excel Tabelle sucht, dort ein paar Zellen weiter rechts die Zellen in eine list packt um diese dann wieder in die 1. Excel Tabelle einzufügen. Nun habe ich bei dieser Funktion:

Code: Alles auswählen

def get_xlsx2_position(xlsx2, list_xlsx1, sheet_name_xlsx2):
    read_xlsx2 = openpyxl.load_workbook(xlsx2)
    sheet2 = read_xlsx2.get_sheet_by_name(sheet_name_xlsx2)
    
    cell_xlsx2 = "placeholder"
    vertical_xlsx2 = 1
    position_list_xlsx2 = []
    
    while cell_xlsx2 != None:
        cell_xlsx2 = sheet2.cell(row=vertical_xlsx2, column=1).value
        for search_string in list_xlsx1:
            if cell_xlsx2 == search_string:
                position_list_xlsx2.append(vertical_xlsx2)
                print(position_list_xlsx2)
        vertical_xlsx2 += 1
    return position_list_xlsx2
Das Problem, dass mir die position_list_xlsx2 nicht in genau der Reihenfolge, in der die search_strings der list_xlsx1 gereiht sind abgespeichert werden.
Sondern beginnend mit dem niedrigsten search_string (zum Verständnis es sind alles Zahlen also die niedrigste Zahl, diese wird zuerst gefunden und daher auch zuerst in die Position_list_xlsx2 abgespeichert).
Logischerweiße müssen sie allerdings genau in der Reihenfolge abgespeichert werden, ansonsten stehen sie im Endeffekt an falschen Positionen in der erste Excel Tabelle.

Kann mir jemand kurz verraten wie ich sie in der richtigen Reihenfolge in die Position_list_xlsx2 bekomme?

Mfg
VoLLioMenTT
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ich habe ein Problem, dass nachzuvollziehen bzw zu versehen, was du meinst... Ein kleines Beispiel mit Werten wäre gut.

Grundsätzlich ist die Reihenfolge bei Listen aber fix (solange du nicht explizit ein `sort` oder so drauf anwendest). Wenn du über eine n-elementige Liste iterierst, werden die Elemente von 0 bis n durchlaufen. Wenn du mit `append()` Werte einer Liste hinzufügst, dann werden diese immer am Ende, also hinter das letzte Element eingefügt. Python sortiert bei Listen von sich auch nichts um.

Gruß, noisefloor
VoLLioMenTT
User
Beiträge: 21
Registriert: Montag 16. Oktober 2017, 16:00

Erstmal danke für die schnelle Antwort, hier nochmal besser erklärt:

Das Problem liegt eigentlich nur an der while und for Schleife:

Code: Alles auswählen

while cell_xlsx2 != None:
        cell_xlsx2 = sheet2.cell(row=vertical_xlsx2, column=1).value
        for search_string in list_xlsx1:
            if cell_xlsx2 == search_string:
                position_list_xlsx2.append(vertical_xlsx2)
        vertical_xlsx2 += 1
Dabei rennt die for Schleife für jeden string in der list (list_xlsx1) durch und wenn der search string der selbe ist wie der über die while schleife in der Excel Zelle gefundene string in (cell_xlsx2) soll er mir die vertikale Position in die position_list_xlsx2 abspeicher.
Allerdings hätte ich gerne, dass er erst alles nach dem ersten eintrag in der list (list_xlsx1) durchst dann nach dem 2. eintrag und so weiter.
Denn so wie der Code momentan geschrieben ist, findet er nicht den ersten string zuerst und trägt dessen Position in die list, sondern einen string irgendwo mitten drin und ich kann nunmal nur etwas damit anfangen, wenn sie genau in der selben Reihenfolge gefunden werden.

Ich hoffe die Erklärung reicht, wenn nicht kann ich es gerne noch detailierter probieren.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@VoLLioMenTT: dann mußt Du halt die Schleifen umdrehen. Am besten liest Du den Inhalt von xlsx2 in eine passende Datenstruktur, also ein Wörterbuch; dann sparst Du Dir auch die Suche per for-Schleife.
VoLLioMenTT
User
Beiträge: 21
Registriert: Montag 16. Oktober 2017, 16:00

Was genau meinst du mit "die Schleifen umdrehen"?

Anfangs hatte ich das ganze schon so strukturiert:

Code: Alles auswählen

for search_string in list_xlsx1:
        while cell_xlsx2 != None:
            cell_xlsx2 = sheet2.cell(row=vertical_xlsx2, column=1).value
            if cell_xlsx2 == search_string:
                position_list_xlsx2.append(vertical_xlsx2)
            vertical_xlsx2 += 1
Dabei gibt er mir dann allerdings nur die Position des ersten items aus und keine weitere.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@VoLLioMenTT: so funktioniert Programmieren nicht. Irgendetwas zusammenzubauen, das man nicht versteht, führt selten zu einem funktionierenden Programm. Versuch das Programm gut zu strukturieren. Am besten im ersten Schritt die Daten in eine passende Datenstruktur (Wörterbuch) lesen, dann Verarbeiten (also zusammenführen der beiden Tabellen) und zum Schluß die Ausgabe.
VoLLioMenTT
User
Beiträge: 21
Registriert: Montag 16. Oktober 2017, 16:00

Ich hab das ganze jetzt stattdessen mit dictionarys aufgebaut, allerdings habe ich immernoch keine Ahnung wie ich mir eine for schleife sparen kann wenn ich an diese while schleife komme.

Und wenn ich eine verwenden will, sieht man ja das ich leider nicht weiß wie.

Könntest du deine Antwort vl nochmal anders formulieren? Vielleicht komme ich dann dahinter.
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Keiner kann raten, wie dein aktueller Code aussieht. Und auch nicht, wie die resultierende Datenstruktur ausschaut. Dazu musst du beides schon posten.
VoLLioMenTT
User
Beiträge: 21
Registriert: Montag 16. Oktober 2017, 16:00

Also beim neuesten Code habe ich gar keine Ausgabe da ich nicht weiß was ich mit dem dictionary anstellen soll:

Code: Alles auswählen

def dic_xlsx2(xlsx2, dic_xlsx1):
    read_xlsx2 = openpyxl.load_workbook(xlsx2)
    sheet2 = read_xlsx2.get_active_sheet()
    
    cell_xlsx2 = "placeholder"
    vertical_xlsx2 = 1
    dic_xlsx2 = []
    
    while cell_xlsx2 != None:
        cell_xlsx2 = sheet2.cell(row=vertical_xlsx2, column=1).value
        if cell_xlsx2 in dic_xlsx1:
            #???????????????????#
        vertical_xlsx2 += 1
    
    return dic_xlsx2
Dann gibt es noch die 2 Möglichkeiten mit lists die ich oben bereits gepostet habe.
Wenn ich dabei die while Schleife in die for Schleife gebe bekomme ich nur die Position des erstens items aus der list ausgegeben und keine weiteren, dafür beginnt er allerdings mit dem ersten.

Oder die Möglichkeit das ich die for Schleife in die While schleife gebe wie ebenfalls oben bereits gepostet, dabei bekomme ich alle Positionen der Items ausgegeben, allerdings arbeitet er sie nicht der reihe nach ab sondern findet zuerst die Position des items das den niedrigsten Wert hat.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@VoLLioMenTT:

1. Programmieren ist nicht raten.
2. Solange du den hier mehrfach geäußerten Wunsch der Hilfswilligen komplett ignorierst, mal ein Schnipsel der Ausgangsdatenstruktur und die gewünschte Zieldatenstruktur zu posten, wird das so wie so nichts.

Gruß, noisefloor
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nur weil du irgend etwas dict nennst ist es noch lange kein dict. Das ist immer noch eine Liste.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@VoLLioMenTT: in Deinem ersten Post hast Du geschrieben, dass im 2. Excel in der ersten Spalte Namen stehen, und in weiteren Werte, die den Namen zugeordnet sind. Das ist klassisch in Wörterbuch. Daher solltest Du im ersten Schritt das Excel komplett lesen und daraus ein Wörterbuch bauen, das Namen -> Werte zuordnet.

Erst wenn das erledigt ist, kannst Du Dein 1. Excel öffnen, Dir zu den Namen, die darin stehen, die passenden Werte aus dem Wörterbuch geben lassen und was auch immer damit machen.
VoLLioMenTT
User
Beiträge: 21
Registriert: Montag 16. Oktober 2017, 16:00

@noisefloor
Tut mir sehr leid, es war nicht meine Absicht das zu ignorieren, ich dachte die Beschreibung reicht womöglich und ich konnte mir bisher nicht genügend Zeit für einen anständigen Post in diesem Forum nehmen. Selbstverständlich bin ich euch für eure Hilfe sehr dankbar.

Das Programmieren kein raten ist weiß ich selbstverständlich auch, ich habe ja auch das gesamte Programm bisher ohne größere Probleme runtergeschrieben, nur bei dieser Funktion habe ich ein Problem das ich logisch nicht lösen konnte und habe etwas planlos rumprobiert und die Ergebnisse hier reingestellt mit der Hoffnung sie könnten euch eventuell helfen.

@__deets__
Ja das weiß ich auch, ich habe nur nachdem ich das ganze mit dictionarys aufgebaut habe, es nochmal kurz zu lists gemacht weil ich eine Idee hatte, die mir allerdings trotzdem nicht weitergeholfen hat und bei dic_xlsx2 vergessen es wieder rückgängig zu machen. dic_xlsx1 wäre in diesem fall wirklich ein dictionary.

Bevor ich die Ausgabe des Scripts poste hier nochmal eine detailierte Beschreibung des Programms:

Das Programm soll aus einer Excel Datei einige Zellen in eine liste packen in denen Artikelnummern stehen. (Das Funktioniert ohne Probleme)
Danach soll es zur zweiten Excel Tabelle gehen und dort einige Zellen nach genau diesen Artikelnummern durchsuchen und sich die vertikale Position dieser Artikelnummer in eine weitere liste eintragen. (Da liegt mein Problem, genauere Beschreibung bei der Ausgabe).
Anschließend soll es weiterarbeiten in der zweiten Excel Tabelle und zwar insofern das es Zellen mit der selben vertikalen Position die zuvor in einer list gespeichert wird und einer festen horizontalen Position in eine liste speichert. (Das Funktioniert ebenfalls ohne Probleme)
Danach geht es wieder zur ersten Excel Tabelle zurück und trägt die zuvor in der liste abgespeicherten Zellen aus der zweiten Excel Tabelle in die erste ein. (Und auch das geht ohne Probleme)

Nun zur gewünschten und zur tatsächlichen Ausgabe.

Code: Alles auswählen

def get_xlsx2_position(xlsx2, list_xlsx1):
    read_xlsx2 = openpyxl.load_workbook(xlsx2)
    sheet2 = read_xlsx2.get_active_sheet()
    
    cell_xlsx2 = "placeholder"
    vertical_xlsx2 = 1
    position_list_xlsx2 = []

    while cell_xlsx2 != None:
        for search_string in list_xlsx1:
            cell_xlsx2 = sheet2.cell(row=vertical_xlsx2, column=1).value
            if cell_xlsx2 == search_string:
                position_list_xlsx2.append(vertical_xlsx2)
        vertical_xlsx2 += 1
    
    return position_list_xlsx2
Mit diesem Code bekomme ich diese Ausgabe:
[501, 506, 690, 691, 794, 938, 1070, 1075, 1641, 1747, 2601, 3065, 3222, 3239, 3326, 3338, 3362, 3373, 3497, 3596]

Die Artikelnummern in der list_xlsx1 sind folgende:
[8806500, 8106235, 8601800, 8601060, 2377090, 2377880, 8611020, 8611180, 8612080, 8612260, 2500310, 2500400, 3110000, 3240100, 3240200, 7240220, 4118000, 2573000, 4377000, 8800330]

Und wie man sieht findet er zuerst die niedrigste Artikelnummer "2377090" und trägt auch als erstes dessen Position in die position_list_xlsx2.

Um mit der list position_list_xlsx2 allerdings in den weiteren Funktionen etwas anfangen zu können muss ich erst die Position der Artikelnummer "8806500", dann "8106235" und so weiter finden.

@Sirius3
Du bzw. ihr wisst es bestimmt besser, aber ich denke das ein dictionary anstatt einer list mit in diesem Fall nicht weiterhilft (siehe oben Beschreibung des Programms), aber ich lasse mich gerne eines besseren belehren.

Ich nehme an das ich einfach nur etwas an diesen 2 Schleifen ändern muss um zu meinem gewünschten Ergebnis zu kommen, doch ich weiß leider nicht was.

Ich hoffe sehr diese Beschreibung reicht diesmal aus und tut mir leid euch davor mit den anderen Posts in die ich zu wenig Zeit investiert habe, eure Zeit geraubt zu haben.

MfG
VoLLioMenTT
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

aha, jetzt ist das Ziel zumindest klar(er).

Ich sehe jetzt auch noch nicht wirklich, wo dein Fehler ist, aber so funktioniert:

Inhalt der Excel-Datei (ein Blatt namens "Tabelle1", zwei Spalten namens "A" und "B":

Code: Alles auswählen

A              B
1234567	foo
2345678	bar
8106235	spam
8601800	egg
4567890	python
8806500	julia
8106235	erlang
Python3 Code:

Code: Alles auswählen

import openpyxl
from collections import OrderedDict
item_codes = [8806500, 8106235, 8601800]
workbook =openpyxl.load_workbook('workbook2.xlsx')
ws = workbook.get_sheet_by_name('Tabelle1')
positions_per_item = OrderedDict()
for item_code in item_codes:
    positions = []
    for row_number, cell in enumerate(ws['A{}:A{}'.format(ws.min_row,
                                                          ws.max_row)], 
        start=1):
        if cell[0].value == item_code:
            positions.append(row_number)
    positions_per_item[item_code] = positions
for k, v in positions_per_item.items():
    print('{}: {}'.format(k, v))
Gruß, noisefloor
VoLLioMenTT
User
Beiträge: 21
Registriert: Montag 16. Oktober 2017, 16:00

@noisefloor

Nun Funktioniert alles wie geplant, vielen dank für deine/eure hilfe.

MfG
VoLLioMenTT
Antworten