• Członkowie 22 posty
    2 czerwca 2025 22:41

    Mam plik txt z jednym stringiem postaci:

    1 Warszawa powiat Warszawa mazowieckie 1 861 644 517,2 km² 2 Kraków powiat Kraków małopolskie 804 237 326,9 km² 3 Łódź powiat Łódź łódzkie 655 279 293,3 km² 4 Wrocław powiat Wrocław dolnośląskie 674 132 292,8 km² ... ... ... ...
    

    (dane pochodzą z www.polskawliczbach.pl/Miasta)

    "Splitnałem" sobie ten string po "km.kw" i mam poszczególne miasta, ale jeszcze potrzebuje to podzielić na kolumny:

    l.poj, miasto, powiat, województwo, ludność i powierzchnia w km.kw.

    Niby nic trudnego ;), ale zastanawiam się jakbyście to zrobili z użyciem modułu re.

    Ja to zrobiłem w dwóch linijkach, bez regex, ale uważam to za mniej elegancki sposób i chętnie zobaczę jak się z tym uporać z regex :)

    Pierwsze 4 linie to:

    data = ['1 Warszawa powiat Warszawa mazowieckie 1 861 644 517,2', '2 Kraków powiat Kraków małopolskie 804 237 326,9', '3 Łódź powiat Łódź łódzkie 655 279 293,3', '4 Wrocław powiat Wrocław dolnośląskie 674 132 292,8']
    

    Ktoś da radę?

  • 3 czerwca 2025 00:18

    Bez regexu:

    data = "1 Warszawa powiat Warszawa mazowieckie 1 861 644 517,2 km² 2 Kraków powiat Kraków małopolskie 804 237 326,9 km² 3 Łódź powiat Łódź łódzkie 655 279 293,3 km² 4 Wrocław powiat Wrocław dolnośląskie 674 132 292,8 km²"
    
    clean_data = []
    for row in data.split("km²"):
        if not row:
            break
    
        no, row = row.strip().split(" ", 1)
        name, row = row.split(" powiat ")
        row, surface = row.rsplit(",", 1)
    
        digit_index = None
        for i, c in enumerate(row):
            if c.isdigit():
               digit_index = i
               break
    
        population = row[digit_index:]
        powiat, voivodeship = row[:digit_index].strip().split(" ")
        clean_data.append((no, name, powiat, voivodeship, population, surface))
    
    print(clean_data)
    

    Wynik:

    [('1', 'Warszawa', 'Warszawa', 'mazowieckie', '1 861 644 517', '2'), ('2', 'Kraków', 'Kraków', 'małopolskie', '804 237 326', '9'), ('3', 'Łódź', 'Łódź', 'łódzkie', '655 279 293', '3'), ('4', 'Wrocław', 'Wrocław', 'dolnośląskie', '674 132 292', '8')]
    
  • Członkowie 22 posty
    3 czerwca 2025 12:35

    Cześć, miało być z regex :) Bez regexu to ja już miałem zrobione wczoraj.

    Twoje rozwiązanie działa b. dobrze, ale jest over-engineered (po polsku: przekombinowane) :)
    Widzę, po pierwszych liniach, że szedłeś w dobrym kierunku, ale później zabrakło chyba pomysłu.

    Nie lubię się za bardzo chwalić, ale ja to zrobiłem w dwóch linijkach kodu :) To znaczy najważniejsza rzecz, czyli "podział na kolumny".

    data = data.split(" km² ")
    
    for d in data:
        reszta, powierzchnia = d.rsplit(" ", 1)
        lpoj, miasto, _, powiat, wojewodztwo, ludnosc = reszta.split(" ", 5)
    

    Może ktoś na forum pokusi się o regexa? ;)

  • 3 czerwca 2025 17:19

    Podstawowe pytamie jakie się nasuwa, to po co regex? ;)

    XKCD

    Problem ze splitem po spacji całego wiersza nazywa się Dąbrowa Górnicza, podobno jest tam ulica Dunninga Krugera ;) ale mój kod też tam głupieje, tylko że przy województwie

  • 3 czerwca 2025 17:41

    v2.0:

    data = "1 Warszawa powiat Warszawa mazowieckie 1 861 644 517,2 km² 2 Kraków powiat Kraków małopolskie 804 237 326,9 km² 3 Łódź powiat Łódź łódzkie 655 279 293,3 km² 4 Wrocław powiat Wrocław dolnośląskie 674 132 292,8 km² 29 Gorzów Wielkopolski powiat Gorzów Wielkopolski lubuskie 115 847 85,7 km² 30 Dąbrowa Górnicza powiat Dąbrowa Górnicza śląskie 114 148 188,7 km²"
    
    clean_data = []
    for row in data.split("km²"):
        if not row:
            break
    
        no, row = row.strip().split(" ", 1)
        name, row = row.split(" powiat ")
        row, surface = row.rsplit(",", 1)
    
        digit_index = None
        for i, c in enumerate(row):
            if c.isdigit():
               digit_index = i
               break
    
        population = row[digit_index:]
        powiat, voivodeship = row[:digit_index].strip().rsplit(" ", 1)
        clean_data.append((no, name, powiat, voivodeship, population, surface))
    
    print(clean_data)
    

    Wynik:

    [('1', 'Warszawa', 'Warszawa', 'mazowieckie', '1 861 644 517', '2'), ('2', 'Kraków', 'Kraków', 'małopolskie', '804 237 326', '9'), ('3', 'Łódź', 'Łódź', 'łódzkie', '655 279 293', '3'), ('4', 'Wrocław', 'Wrocław', 'dolnośląskie', '674 132 292', '8'), ('29', 'Gorzów Wielkopolski', 'Gorzów Wielkopolski', 'lubuskie', '115 847 85', '7'), ('30', 'Dąbrowa Górnicza', 'Dąbrowa Górnicza', 'śląskie', '114 148 188', '7')]
    
  • Członkowie 22 posty
    4 czerwca 2025 12:38

    Regex wydawał mi się bardziej elegancki i bardziej profesjonalny. Ale mogę nie mieć racji.

    Co do nazw dwuczłonowych, to rzeczywiście to przeoczyłem. Kodzik napisałem na szybko i gruntownie nie sprawdzałem miasto po mieście.

    Zauważyłem u Ciebie (obie wersje) jeszcze, że zgubiłeś informację o powierzchni w km.kw - masz w ostatniej kolumnie tylko pojedynczą cyfrę w wynikach (cześć cyfr z powierzchni powędrowała do populacji). .....A wydawałoby się, że to trywialny przykład :)

    Dzięki za udział w wyzwaniu! ;)

    BTW. W skrypcie forum dodałbym numerację linii kodu - zawsze łatwiej się odnieść do kodu.

  • 4 czerwca 2025 12:54

    Faktycznie, ale to łatwe do poprawienia (trzeba zastąpić przecinek spacją w rsplicie).

    Nie ma nic eleganckiego w długich patternach regexu, i często parser który regexa nie używa może być czytelniejszy, nie mówiąc o szybkości działania. IMHO