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

Enlace de código

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?

0
user11350745 9 may. 2019 a las 19:57

4 respuestas

La mejor respuesta

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)}

2
Devesh Kumar Singh 9 may. 2019 a las 17:11

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.

1
Austin 9 may. 2019 a las 17:10
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.

0
ipol 9 may. 2019 a las 17:49

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

0
Sam Mason 9 may. 2019 a las 20:17