2011-11-10 14 views
8

Mam matrycę 6x6 jako listę list w python. Macierz jest podzielona na 4 bloki kwadratowe o rozmiarze 3x3. Chcę sposobu na przeniesienie tylko jednego bloku. Mogę to zrobić za pomocą tradycyjnej metody przechodzenia przez każdy element i kopiowania go do innej tablicy iz powrotem itd., Ale chcę sprawdzić, czy istnieje lepszy sposób (transponowanie macierzy w pythonie można wykonać w jednym wierszu za pomocą metoda zip)transpozycja/obracanie bloku macierzy w pytonie

dla np to reprezentacja macierzy i jego bloki

block 1 block 2 
+-------+-------+ 
| . . . | . . . | 
| . . 2 | 1 . . | 
| . . . | . . . | 
+-------+-------+ 
| . . . | . . . | 
| . . . | . . . | 
| . 1 . | . . . | 
+-------+-------+ 
block 3 block 4 

i obracanie (3, po prawej) powinno skutkować tym

block 1 block 2 
+-------+-------+ 
| . . . | . . . | 
| . . 2 | 1 . . | 
| . . . | . . . | 
+-------+-------+ 
| . . . | . . . | 
| 1 . . | . . . | 
| . . . | . . . | 
+-------+-------+ 
block 3 block 4 

Chcę znaleźć sposób który przyjmuje numer bloku i obraca tylko ten blok w lewo lub w prawo . Czy jest jakiś łatwy sposób to zrobić?

+1

Czy operacja powinna być na miejscu? –

+0

tak, Musi być na miejscu, lub przynajmniej wynik musi być zapisany z powrotem do oryginalnej matrycy – randomThought

Odpowiedz

5

budynku na pomysł Sven Marnach do korzystania np.rot90, tutaj jest wersja, która obraca ćwiartkę zgodnie z ruchem wskazówek zegara (zgodnie z życzeniem?). W kluczowym etapie

block3[:] = np.rot90(block3.copy(),-1) 

copy() stosowany jest na prawej stronie (RHS). Bez wartości copy(), ponieważ wartości są przypisane do block3, podstawowe dane używane w RHS również zostaną zmienione. To mylące wartości używane w przydziałach podrzędnych. Bez copy() wiele różnych wartości jest rozłożonych na około block3.

Nie widzę sposobu na wykonanie tej operacji bez kopii.

import numpy as np 
a = np.arange(36).reshape(6, 6) 
print(a) 
# [[ 0 1 2 3 4 5] 
# [ 6 7 8 9 10 11] 
# [12 13 14 15 16 17] 
# [18 19 20 21 22 23] 
# [24 25 26 27 28 29] 
# [30 31 32 33 34 35]] 
block3 = a[3:6, 0:3] 

# To rotate counterclockwise 
block3[:] = np.rot90(block3.copy()) 
print(a) 
# [[ 0 1 2 3 4 5] 
# [ 6 7 8 9 10 11] 
# [12 13 14 15 16 17] 
# [20 26 32 21 22 23] 
# [19 25 31 27 28 29] 
# [18 24 30 33 34 35]] 

# To rotate clockwise 
a = np.arange(36).reshape(6, 6) 
block3 = a[3:6, 0:3] 
block3[:] = np.rot90(block3.copy(),-1) 
print(a) 
# [[ 0 1 2 3 4 5] 
# [ 6 7 8 9 10 11] 
# [12 13 14 15 16 17] 
# [30 24 18 21 22 23] 
# [31 25 19 27 28 29] 
# [32 26 20 33 34 35]] 
0

Czy byłoby rozwiązaniem do zdefiniowania macierzy jako słownika bloków i bloku jako listy list? W przykładzie (zastąpić transpozycję() z funkcji użyć do jej transpozycji):

Matrix={1:block1,2:block2,3:block3,4:block4} 
block3=transpose(block3) 
Matrix[3]=block3 
+0

nie tak naprawdę, ponieważ muszę wykonać inne operacje macierzy, których struktura nie pozwoli lub będzie się komplikować. – randomThought

0

Oto sposób, aby obrócić „blok” z matrycy podałeś:

matrix = [[0,1,2],[3,4,5],[6,7,8]] 

def rotate(m, right): 
    rm = [] 
    for i in range(0,len(m)): 
     if right: 
      rm.append([row[i] for row in reversed(m)]) 
     else: 
      rm.append([row[i] for row in m]) 
    return rm 

right jest Bool
ta zwróci list of lists

można również użyć:

def rotate(m, right): 
    if right: 
     return list(zip(*reversed(m))) 
    else: 
     return list(zip(*m)) 

ale to zwróci list of tuples


EDIT:

Jeśli mówimy o matrycy typu:

matrix = [[[1,2,3],[4,5,6],[7,8,9]], # block 1 
      [[1,2,3],[4,5,6],[7,8,9]], # block 2 
      [[1,2,3],[4,5,6],[7,8,9]], # block 3 
      [[1,2,3],[4,5,6],[7,8,9]] # block 4 
     ] 

chcesz zablokować dostęp 3 za pomocą matrix[2]

dzięki czemu zabawa obraca się ction będzie używany jak:
rotate(matrix[2], True) #rotate block 3, right

+0

tak. cała macierz lista list liczb. – randomThought

+0

Lista list liczb to macierz, którą podałem w przykładzie, jeśli jest listą listy numerów, możesz wybrać trzeci blok, po prostu wpisując "rotate (matrix [2], True/False)" – Serdalis

+0

ale jak wyodrębnić tylko blok, aby przekazać go do funkcji? – randomThought

4

Na co warto, oto jak prosta to na w NumPy:

>>> a = numpy.arange(36).reshape(6, 6) 
>>> a 
array([[ 0, 1, 2, 3, 4, 5], 
     [ 6, 7, 8, 9, 10, 11], 
     [12, 13, 14, 15, 16, 17], 
     [18, 19, 20, 21, 22, 23], 
     [24, 25, 26, 27, 28, 29], 
     [30, 31, 32, 33, 34, 35]]) 
>>> block3 = a[3:6, 0:3] 
>>> block3[:] = numpy.rot90(block3, 1).copy() 
>>> a 
array([[ 0, 1, 2, 3, 4, 5], 
     [ 6, 7, 8, 9, 10, 11], 
     [12, 13, 14, 15, 16, 17], 
     [20, 26, 32, 21, 22, 23], 
     [26, 25, 31, 27, 28, 29], 
     [20, 26, 20, 33, 34, 35]]) 
+0

+1 dla numpy.rot90. Zauważ jednak, że kopiowanie prawej strony na 'block3 [:]' w miejscu ma niepożądany efekt uboczny - ponieważ nowe wartości są przypisane do 'bloku3', wartości leżące po prawej stronie również zostają nadpisane, pozostawiając wiele kopii o tej samej wartości w wyniku. – unutbu

+0

@unutbu: Dzięki za wskazanie tego. Nawet nie patrzyłem na wynik - byłem pewien, że 'numpy.rot90()' zwraca nową tablicę, a nie widok. –