Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

231
Views
¿Manera numpyica de ordenar un ndarray en el sentido de las agujas del reloj?

Estoy tratando de ordenar un ndarray numpy en el sentido de las agujas del reloj (en orden ascendente). Puede entenderlo como tomar todos los valores de la matriz, ordenarlos y luego colocarlos en una espiral en el sentido de las agujas del reloj en una nueva matriz con la misma forma. Las direcciones de la espiral en el sentido de las agujas del reloj se muestran a continuación:

ingrese la descripción de la imagen aquí

Por ejemplo, supongamos que tengo una matriz de

 import numpy as np a1 = np.array(([2, 4, 6], [1, 5, 3], [7, 9, 8]))

La salida esperada es

 np.array([[1, 2, 3], [8, 9, 4], [7, 6, 5]])

Si tengo una matriz de

 a2 = np.array(([2, 4, 6], [1, 5, 3], [7, 9, 8], [12, 11, 10]))

La salida esperada es

 np.array([[1, 2, 3], [10, 11, 4], [9, 12, 5], [8, 7, 6]])

Lo que he probado hasta ahora

Mi idea es rastrear el índice de fila x y el índice de columna y del iterador en movimiento y el índice actual cur de la lista aplanada ordenada sa . El número de filas por recorrer ( lenr ) y el número de columnas por recorrer ( lenc ) se restan en 1 una vez que el iterador en movimiento pasa lenr filas horizontalmente y lenc columnas verticalmente. Aquí está la función que logré escribir:

 def clockwise_sorted(a, key=None, reverse=False): nr, nc = a.shape res = a.tolist() sa = a.ravel().tolist() if key is None: sa.sort(reverse=reverse) else: sa.sort(key=key, reverse=reverse) res[0] = sa[:nc] cur, lenr, lenc = nc, nr - 1, nc - 1 x, y = 0, nc - 1 while (lenc > 0 and lenr > 0): # go down, then go left for _ in range(lenr): x += 1 res[x][y] = sa[cur] cur += 1 for _ in range(lenc): y -= 1 res[x][y] = sa[cur] cur += 1 lenr -= 1 lenc -= 1 # go up, then go right for _ in range(lenr): x -= 1 res[x][y] = sa[cur] cur += 1 for _ in range(lenc): y += 1 res[x][y] = sa[cur] cur += 1 lenr -= 1 lenc -= 1 return np.array(res)

Para matrices cuadradas, mi código funciona bien:

 print(clockwise_sorted(a1)) #[[1 2 3] # [8 9 4] # [7 6 5]] #%timeit 5.98 µs ± 413 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Pero no funciona para matrices no cuadradas:

 print(clockwise_sorted(a2)) #[[ 1 2 3] # [10 11 4] # [ 9 9 5] # [ 8 7 6]]

Claramente, pierde el 12 en [2,1] .

Tenga en cuenta que no espero que entienda y corrija mi código. No me gusta mucho mi código porque siento que debería haber más formas numpyic de hacer esto. Por lo tanto, quiero ver algunas soluciones numpyic. Sin embargo, sería bueno si alguien puede comentar sobre lo que está mal con mi código.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Es probable que esta no sea la solución más numpy, pero creo que es una solución Pythonic ordenada, ya que es una función generadora que produce coordenadas en espiral en el sentido de las agujas del reloj que luego se usa para indexar la matriz numpy (que debe transponerse dos veces para obtener las coordenadas correctas, pero eso es maní...).

 import numpy as np def spiral_coords(w, h): maxx = w - 1 maxy = h - 1 minx = miny = 0 while (minx, miny) != (maxx, maxy): for x in range(minx, maxx): # right yield (x, miny) yield (maxx, miny) # upper-right corner for y in range(miny + 1, maxy): # down yield (maxx, y) yield (maxx, maxy) # lower-right corner for x in range(maxx - 1, minx, -1): # left yield (x, maxy) yield (minx, maxy) # lower-left corner for y in range(maxy - 1, miny, -1): # up yield (minx, y) minx += 1 miny += 1 maxx -= 1 maxy -= 1 yield (minx, miny) # final point def clockwise_sorted(a): a = aT nr, nc = a.shape sa = a.ravel() sa.sort() res = np.zeros_like(a) for (x, y), v in zip(spiral_coords(nr, nc), sa): res[x, y] = v return res.T a2 = np.array( [ [2, 4, 6], [1, 5, 3], [7, 9, 8], [12, 11, 10], ] ) print(a2) print(clockwise_sorted(a2))

Esto produce

 [[ 2 4 6] [ 1 5 3] [ 7 9 8] [12 11 10]] [[ 1 2 3] [10 11 4] [ 9 12 5] [ 8 7 6]]

Si no necesita necesariamente Numpy, también puede usar el mismo generador para convertir en espiral cualquier cosa, por ejemplo, un mapeo de coordenadas a letras:

 coords = {(x, y): c for (x, y), c in zip(spiral_coords(6, 5), "Hello World! This is a spiral!")} for y in range(5): print("".join(coords.get((x, y), " ") for x in range(6)))

salidas

 Hello is aW sal! o iripsr hT !dl
over 4 years ago · Santiago Trujillo Report

0

Puede usar numpy.rot90 con recursividad para girar en el sentido de las agujas del reloj sobre la matriz. Ordene los valores de la matriz después de cambiar a 1d y edite los valores en la matriz por ella

 def rotate(matrix, arr): if not len(matrix): return matrix[0] = arr[:len(matrix[0])] rotate(np.rot90(matrix[1:]), arr[len(matrix[0]):]) a1 = np.array(([2, 4, 6], [1, 5, 3], [7, 9, 8])) sorted_arr = sorted(a1.ravel()) rotate(a1, sorted_arr) print(a1)

Producción

 [[1 2 3] [8 9 4] [7 6 5]]
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!