Tengo una tupla, que me da algo como esto:
(array([115, 115, 295], dtype=int64), array([377, 378,404], dtype=int64))
Ahora quiero convertirlo como un conjunto como este:
{(115,377),(115,378),(295,404)}
Actualmente estoy usando este enfoque:
def edges2cordinate(edges):
l = int(len(edges[0]))
res=set()
for i in range (0,len):
res.add((edges[0][i],edges[1][i]))
return res
Pero me da un error.
Rastreo (última llamada más reciente): Archivo "F: \ canny_vertices.py", línea 40, en impresión (edge2cordinate (índices)) Archivo "F: \ canny_vertices.py", línea 16, en edge2cordinate para i en rango (0, len): TypeError: el objeto 'builtin_function_or_method' no puede interpretarse como un entero
¿Qué me estoy perdiendo?
4 respuestas
En su código anterior, desearía hacer range (0,l)
en lugar de range (0,len)
, ya que ha guardado su variable de longitud en l
, por lo que desea pasar esa longitud a {{X3} } variable en lugar de función incorporada len
Una vez que hagas eso, el código original funciona bien
def edges2cordinate(edges):
l = int(len(edges[0]))
res=set()
for i in range (0,l):
res.add((edges[0][i],edges[1][i]))
return res
print(edges2cordinate([[115, 115, 295],[377, 378,404]]))
La salida será {(295, 404), (115, 378), (115, 377)}
Pero esto también se puede hacer fácilmente a través de zip
, donde desempaquetamos la lista de listas, la pasamos a zip
como argumento y luego convertimos el iterador comprimido de nuevo a set
, tenga en cuenta que vemos una salida desordenada aquí debido a set
li = [[115, 115, 295],[377, 378,404]]
print(set(zip(*li)))
La salida será {(295, 404), (115, 378), (115, 377)}
Para revertir los elementos, simplemente inviértalos al crear el conjunto a través de la comprensión de la lista invirtiendo elementos individuales de la tupla.
li = [[115, 115, 295],[377, 378,404]]
print(set((y,x) for x, y in zip(*li)))
La salida será {(404, 295), (377, 115), (378, 115)}
Utilice zip
con el desempaquetado:
list(zip(*tupl)) # where tupl is your tuple
Que genera una lista de valores en oposición a sus expectativas. Pero supongo que esto probablemente sea más adecuado ya que el conjunto eliminará duplicados y no tiene orden.
def edges2cordinate(edges):
res = set()
for i in range(len(edges[0])):
res.add((edges[0][i], edges[1][i]))
return res
edge = ([115, 123, 295], [377, 378, 404])
res = edges2cordinate(edge)
set(reversed(list(res)))
Esto también proporciona el resultado correcto {(115, 377), (115, 378), (295, 404)}
, que es una solución más simple si no está familiarizado con zip
. La razón por la cual su código no funcionó correctamente se respondió correctamente anteriormente.
Para explicar cómo ubicarse entre todas las otras respuestas, comenzamos con una versión ordenada (y fija) del código original de los OP:
def edges2cordinate(edges):
num_entries = len(edges[0])
res = set()
for i in range(0, num_entries):
res.add((edges[0][i], edges[1][i]))
return res
La primera limpieza ocurre después de notar que range()
permite que se pase un solo argumento, lo que hace que cuente desde cero hasta ese argumento. también notamos que num_entries
solo se usa una vez, por lo que podemos moverlo a donde se usa, mostrándonos:
def edges2cordinate(edges):
res = set()
for i in range(len(edges[0])):
res.add((edges[0][i], edges[1][i]))
return res
Segundo, observe que seguimos obteniendo los elementos primero y segundo de edges
en cada iteración del bucle for
. Python nos brinda "expresiones de asignación" (< a href = "https://www.python.org/dev/peps/pep-0572/" rel = "nofollow noreferrer"> PEP 572 ) que nos permite escribir esto como:
def edges2cordinate(edges):
first_arr, second_arr = edges
res = set()
for i in range(len(first)):
res.add((first_arr[i], second_arr[i]))
return res
Y debería ser un poco más rápido, porque solo necesitamos sacar los elementos una vez en lugar de cada iteración de bucle.
Cada respuesta ha apuntado a usar zip()
para hacer esto código más conciso. usa zip
dándole varias cosas que se pueden repetir, como list
s o sus matrices, y las comprime devolviéndole tuplas que contienen elementos de las cosas que le dio. p.ej:
list(zip([1,2,3], [4,5,6]))
Evalúa a [(1,4), (2,5), (3,6)]
. la razón del list()
que lo rodea es que (en Python 3) zip
te devuelve un iterador, y pasar este iterador a list()
te da una lista que contiene elementos de ese iterador.
Tercero, el cambio más pequeño para usar zip
en el código anterior sería:
def edges2cordinate(edges):
first_arr, second_arr = edges
res = set()
for first_item_i, second_item_i in zip(first_arr, second_arr):
res.add((first_item_i, second_item_i))
return res
Además, estamos utilizando estas "expresiones de asignación" para desarmar las cosas de forma redundante y juntarlas, de modo que podamos reescribir esto para:
def edges2cordinate(edges):
res = set()
for pair_i in zip(edges[0], edges[1]):
res.add(pair_i)
return res
También podemos cambiar el uso de zip(*edges)
que "desempaqueta" edges
en los argumentos de {{ X2}}, es decir, edges[0]
va al primer parámetro de zip
, edges[1]
va al segundo parámetro, etc.
Otra herramienta que Python le brinda son generador de expresiones, lo que nos permite convertir mucho de esto en una sola línea:
def edges2cordinate(edges):
return set(pair_i for pair_i in zip(*edges))
Pero no estamos "haciendo nada" con esta expresión generadora, por lo que se puede eliminar, llegando al minimalista:
def edges2cordinate(edges):
return set(zip(*edges))
En un comentario de seguimiento, preguntaste cómo invertir el orden de los bordes. una forma sería hacer:
def edges2cordinate(edges):
return set(zip(edges[1], edges[0]))
Que con suerte hará lo obvio. la función sugerida reversed()
probablemente hace lo que usted desea esperar, pero se puede usar como:
def edges2cordinate(edges):
return set(zip(*reversed(edges)))
Para mantenerla mínima
Preguntas relacionadas
Preguntas vinculadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.