Chciałbym wyodrębnić bardzo specyficzną część tablicy 2D w Pythonie za pomocą metody zip() (i uniknąć bałaganu do logiki pętli). Chciałbym używać ZIP, aby osiągnąć coś takiego:

>>> sub_matrix = list(zip([*grid[0:3]]*3))

# Desired output example (Option 1)
[".","4",".", ".",".","4",".",".","."]

# Desired output example (Option 2)
[[".","4","."],  
[".",".","4"],
[".",".","."]]

Pracuję z tablicą 2D poniżej w Pythonie na problemie z praktyką wywiadu.

grid = [[".","4",".",".",".",".",".",".","."],
    [".",".","4",".",".",".",".",".","."],
    [".",".",".","1",".",".","7",".","."],
    [".",".",".",".",".",".",".",".","."],
    [".",".",".","3",".",".",".","6","."],
    [".",".",".",".",".","6",".","9","."],
    [".",".",".",".","1",".",".",".","."],
    [".",".",".",".",".",".","2",".","."],
    [".",".",".","8",".",".",".",".","."]]

Częścią rozwiązywania problemu polega na zapewnieniu każdego 3 x 3 "regionu" w grze Sudoku zawiera wartości prawne. Chciałbym użyć zip(), aby szybko wyodrębnić część matrycy 3 x 3. Na przykład, obszar górny lewy spowodowałby niepowodzenie testów, ponieważ zawiera 4 dwa razy.

enter image description here

Wiem, że mogę podzbiwić siatkę, aby uzyskać pierwsze trzy rzędy w następujący sposób:

    >>> sub_grid = grid[0:3]
    >>> print(sub_grid)
    [['.', '4', '.', '.', '.', '.', '.', '.', '.'], 
    ['.', '.', '4', '.', '.', '.', '.', '.', '.'], 
    ['.', '.', '.', '1', '.', '.', '7', '.', '.']]

Zmodyfikowałem drukowanie trochę, aby było oczywiste, ale w tym momencie chciałbym zamknąć trzy tablice za pomocą "kroku" 3, dzięki czemu każda nowa tablica zapina 3 wartości z każdej tablicy przed przejściem do Następny.

W będzie ukryty aż do odblokowanego)

Każda pomoc jest mile widziana. Dzięki.

3
Scott Skiles 25 czerwiec 2017, 20:10

3 odpowiedzi

Najlepsza odpowiedź

Brak zamka na zamek [row[:3] for row in grid[:3]]

4
woodpav 25 czerwiec 2017, 17:18

TL; DR

Aby uruchomić bloki prowadzić tę liniową:

[reduce(lambda a, b: a+b, item) for l in [zip(*row) for row in zip(*[iter([zip(*[iter(row)]*3) for row in grid])]*3)] for item in l]

Wyjaśnienie krok po kroku

Najpierw spójrzmy, jak użyć zip:

chunks = [zip(*[iter(row)]*3) for row in grid]

[
    [('.', '4', '.'), ('.', '.', '.'), ('.', '.', '.')],
    [('.', '.', '4'), ('.', '.', '.'), ('.', '.', '.')],
    [('.', '.', '.'), ('1', '.', '.'), ('7', '.', '.')],
    [('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')],
    [('.', '.', '.'), ('3', '.', '.'), ('.', '6', '.')],
    [('.', '.', '.'), ('.', '.', '6'), ('.', '9', '.')],
    [('.', '.', '.'), ('.', '1', '.'), ('.', '.', '.')],
    [('.', '.', '.'), ('.', '.', '.'), ('2', '.', '.')],
    [('.', '.', '.'), ('8', '.', '.'), ('.', '.', '.')]
]

Widzisz, jak każdy rząd został podzielony na kawałki rozmiaru trzy. Wiersze powinny być również podzielone, więc biegamy:

blocks = zip(*[iter(chunks)]*3)

[
    (
        [('.', '4', '.'), ('.', '.', '.'), ('.', '.', '.')],
        [('.', '.', '4'), ('.', '.', '.'), ('.', '.', '.')],
        [('.', '.', '.'), ('1', '.', '.'), ('7', '.', '.')]
    ), (
        [('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')],
        [('.', '.', '.'), ('3', '.', '.'), ('.', '6', '.')],
        [('.', '.', '.'), ('.', '.', '6'), ('.', '9', '.')]
    ), (
        [('.', '.', '.'), ('.', '1', '.'), ('.', '.', '.')],
        [('.', '.', '.'), ('.', '.', '.'), ('2', '.', '.')],
        [('.', '.', '.'), ('8', '.', '.'), ('.', '.', '.')]
    )
]

Daje nam nam bloki. W przypadku ekstrakcji ma sens, aby najpierw ich transponować:

transposed_blocks = [zip(*row) for row in blocks]

[
    [
        (('.', '4', '.'), ('.', '.', '4'), ('.', '.', '.')),
        (('.', '.', '.'), ('.', '.', '.'), ('1', '.', '.')),
        (('.', '.', '.'), ('.', '.', '.'), ('7', '.', '.'))
    ], [
        (('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')),
        (('.', '.', '.'), ('3', '.', '.'), ('.', '.', '6')),
        (('.', '.', '.'), ('.', '6', '.'), ('.', '9', '.'))
    ], [
        (('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')),
        (('.', '1', '.'), ('.', '.', '.'), ('8', '.', '.')),
        (('.', '.', '.'), ('2', '.', '.'), ('.', '.', '.'))
    ]
]

Widzisz, jak każdy blok jest teraz na własnej linii. Ostatnim krokiem jest połączenie każdej linii na jedną listę:

blocks_as_list = [reduce(lambda a, b: a+b, item)
                  for l in transposed_blocks for item in l]

[
    ('.', '4', '.', '.', '.', '4', '.', '.', '.'),
    ('.', '.', '.', '.', '.', '.', '1', '.', '.'),
    ('.', '.', '.', '.', '.', '.', '7', '.', '.'),
    ('.', '.', '.', '.', '.', '.', '.', '.', '.'),
    ('.', '.', '.', '3', '.', '.', '.', '.', '6'),
    ('.', '.', '.', '.', '6', '.', '.', '9', '.'),
    ('.', '.', '.', '.', '.', '.', '.', '.', '.'),
    ('.', '1', '.', '.', '.', '.', '8', '.', '.'),
    ('.', '.', '.', '2', '.', '.', '.', '.', '.')
]

I skończymy z listą wszystkich bloków. Teraz możesz je sprawdzić przeciwko regułom Sudoku.

2
fafl 17 lipiec 2017, 13:07

zip nie obsługuje w ten sposób w ten sposób podchodzący przez zagnieżdżone struktury. Kolejną alternatywą dla drugiej odpowiedzi jest użycie map i wyodrębnić te plastry.

from operator import itemgetter
list(map(itemgetter(0, 1, 2), grid[0:3]))

Lub, jeśli wolisz:

list(map(lambda x: x[0:3], grid[0:3]))

Jeśli używasz Python2, możesz upuścić dodatkową list(...).

Jeśli chodzi o to, jaką technikę do użycia i dlaczego spójrz na NISKIE Wątek.

Wynik:

[('.', '4', '.'), ('.', '.', '4'), ('.', '.', '.')]
2
cs95 25 czerwiec 2017, 17:33