Dada una matriz 2D (lista de Python), necesito encontrar una nueva 1D que contenga elementos únicos en cada columna. Por ejemplo:

[1, 1, -1, 1, 0]

[1, -1, -1, 3, 4]

[0, 0, 0, -2, -4]

Debería darme, por ejemplo, [1,-1,0,3,4]. Mis pruebas hasta ahora: resultados es una matriz 2D de tamaño 3 filas yn columnas. último es la matriz que almacena el resultado final, mejor dicho, los valores únicos para cada columna. De esta matriz, necesito encontrar una matriz de elementos 1D para que sean diferentes.

last = []    
for i in range(len(results[0])):
    a = results[0][i]
    b = results[1][i]
    c = results[2][i]
    if (a not in last):
        last[i] = a
    elif (b not in last):
        last[i] = b
    elif (c not in last):
        last[i] = c

Pero no siempre da la respuesta correcta. Esto falla para la entrada, por ejemplo:

[1, 2, 3, 3]

[1, 0, -1, 1]

[0, 1, 2, 2]

El resultado debería ser, por ejemplo, [0,1,2,3] o [1,0,3,2] Se agradece cualquier ayuda y sugerencia.

0
ASPire 3 dic. 2020 a las 14:39

2 respuestas

La mejor respuesta

El código de esta respuesta devuelve una lista compuesta por un elemento de cada columna, de modo que esta lista no contiene duplicados.

Fuerza bruta: usar itertools.product en las columnas para iterar a través de cada combinación posible de elementos de cada columna, y devolver la primera que no contiene duplicados.

Código

from itertools import product

def getCombinationWithoutDuplicates(table):
  columns = map(frozenset, zip(*table))
  for combination in product(*columns):
    if len(set(combination)) == len(combination):
      return combination
  return None

Salida

>>> getCombinationWithoutDuplicates([[1, 1, -1, 1, 0],
                                     [1, -1, -1, 3, 4],
                                     [0, 0, 0, -2, -4]])
(0, 1, -1, 3, 4)

>>> getCombinationWithoutDuplicates([[1, 1, -1, 5, 0],
                                     [1, 3, 2, 4, 4],
                                     [0, 1, 2, 5, -4]])
(0, 1, 2, 4, -4)

Explicación del código

  • zip(*table) transpone la lista de listas (por lo que es la lista de columnas en lugar de la lista de filas);
  • map(frozenset, ...) elimina los duplicados de cada columna, lo que no tiene ningún impacto en la solución final pero hace que la fuerza bruta sea más rápida;
  • for combination in product(*columns): itera sobre cada combinación posible de un elemento de cada columna;
  • len(set(combination)) == len(combination) prueba si hay duplicados en la combinación;
  • En la posible situación donde no hay solución, el ciclo for - se ejecutará en su totalidad y el flujo llegará a la última línea return None.

Referencias

0
Stef 7 dic. 2020 a las 18:41

El código en esta respuesta devuelve una lista hecha de un elemento de cada columna, de modo que este elemento no tiene duplicados en su columna.

Usando collections.Counter para obtener el elemento menos común de cada columna. Si la columna contiene un elemento que es único, entonces los elementos únicos son los menos comunes (ocurren una vez).

Código

from collections import Counter

def getUniqueFromColumns(table):
  nbRows = len(table)
  nbCol = len(table[0])
  assert(len(row) == nbCol for row in table)
  return [Counter(row[icol] for row in table).most_common()[-1][0] for icol in range(nbCol)]

Salida

>>> getUniqueFromColumns([[1, 1, -1, 1, 0],
                          [1, -1, -1, 3, 4],
                          [0, 0, 0, -2, -4]])
[0, 0, 0, -2, -4]

>>> getUniqueFromColumns([[1, 1, -1, 5, 0],
                          [1, 3, 2, 4, 4],
                          [0, 1, 2, 5, -4]]) 
[0, 3, -1, 4, -4]

Explicación del código

  • assert(len(row) == nbCol for row in table) asegura que la lista de listas sea realmente un rectángulo;
  • row[icol] for row in table devuelve la columna en el índice icol;
  • Counter(...) cuenta el número de apariciones de cada elemento distinto en la columna;
  • .most_common() devuelve una lista de pares (element, count) ordenados por recuento en orden inverso;
  • .most_common()[-1][0] obtiene el elemento menos frecuente de la columna.

Referencias

0
Stef 3 dic. 2020 a las 12:40