Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

214
Vistas
¿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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda