Compruebe si un elemento está en una lista anidada

en una lista simple siguiente comprobación es trivial:

x = [1, 2, 3] 2 in x -> True 

pero si es una lista de la lista, como por ejemplo:

 x = [[1, 2, 3], [2, 3, 4]] 2 in x -> False 

¿Cómo se puede abordar esto para devolver True ?

Intenta esto, usando la función incorporada. Es la solución más idiomática, y también es eficiente, porque any cortocircuito y se detiene tan pronto como encuentra la primera coincidencia:

 x = [[1, 2, 3], [2, 3, 4]] any(2 in sl for sl in x) => True 

Aquí hay una versión recursiva que funciona para cualquier nivel de anidación.

 def in_nested_list(my_list, item): """ Determines if an item is in my_list, even if nested in a lower-level list. """ if item in my_list: return True else: return any(in_nested_list(sublist, item) for sublist in my_list if isinstance(sublist, list)) 

Aquí hay algunas pruebas:

 x = [1, 3, [1, 2, 3], [2, 3, 4], [3, 4, [], [2, 3, 'a']]] print in_nested_list(x, 2) print in_nested_list(x, 5) print in_nested_list(x, 'a') print in_nested_list(x, 'b') print in_nested_list(x, []) print in_nested_list(x, [1, 2]) print in_nested_list(x, [1, 2, 3]) True False True False True False True 

Puedes usar set.issubset() y itertools.chain() :

 In [55]: x = [[1, 2, 3], [2, 3, 4]] In [56]: {4}.issubset(chain.from_iterable(x)) Out[56]: True In [57]: {10}.issubset(chain.from_iterable(x)) Out[57]: False 

También puede verificar la membresía para múltiples artículos de manera eficiente:

 In [70]: {2, 4}.issubset(chain.from_iterable(x)) Out[70]: True In [71]: {2, 4, 10}.issubset(chain.from_iterable(x)) Out[71]: False 

Esto funcionaría:

 for arr in x: if 2 in arr: print True break 

Recomendaría la respuesta de Oscar ya que any es la opción correcta aquí.

TL; DR

 x = [0, [1, 2, 3], [2, 3, [4, 5, [6], []], [7, 8]]] def find_n(input_list, n): for el in input_list: if el == n or (isinstance(el, list) and find_n(el, n)): return True return False print(find_n(x, 6)) 

Tenga en cuenta que, algo interesante:

 def find_n(input_list, n): return any([el == n or (isinstance(el, list) and find_n(el, n)) for el in input_list]) return (find_n(x, 6)) 

Es más de 50% más lento de ejecutar.

Respuesta (s) original (es)

¿Qué pasa si tienes una profundidad superior a 2? Aquí hay una aproximación al caso genérico:

 x = [0, [1, 2, 3], [2, 3, [4, 5, [6], []], [7, 8]]] def flatten(input_list): flat_list = [] for sublist_or_el in input_list: if isinstance(sublist_or_el, list): for sublist_or_el2 in flatten(sublist_or_el): flat_list.append(sublist_or_el2) else: flat_list.append(sublist_or_el) return flat_list print(6 in flatten(x)) 

Sin embargo, no estoy seguro de la velocidad, pero como dije, ¡es un enfoque que puede ser útil para alguien!

EDITAR – MEJOR (MÁS RÁPIDO) RESPUESTA:

Esto reduce el tiempo necesario (si se encuentra n , en realidad incluso si no se encuentra, aproximadamente la mitad del tiempo en realidad …) al regresar temprano. Esto es un poco más rápido que la respuesta de @Curt F., y más lento que crear una función que asume una profundidad máxima de 2 (la respuesta aceptada).

 x = [0, [1, 2, 3], [2, 3, [4, 5, [6], []], [7, 8]]] def find_n(input_list, n): flat_list = [] for sublist_or_el in input_list: if isinstance(sublist_or_el, list): if find_n(sublist_or_el, n) == True: return True elif sublist_or_el == n: return True return False print(find_n(x, 6)) 

Tiempo rápido (muy hacky, lo siento, ocupado hoy!):

 import time x = [0, [1, 2, 3], [2, 3, [4, 5, [6], []], [7, 8]]] def a(): def flatten(input_list): flat_list = [] for sublist_or_el in input_list: if isinstance(sublist_or_el, list): for sublist_or_el2 in flatten(sublist_or_el): flat_list.append(sublist_or_el2) else: flat_list.append(sublist_or_el) return flat_list return (6 in flatten(x)) def b(): def find_n(input_list, n): flat_list = [] for sublist_or_el in input_list: if isinstance(sublist_or_el, list): if find_n(sublist_or_el, n) == True: return True elif sublist_or_el == n: return True return False return (find_n(x, 6)) zz = 0 for i in range(100000): start_time = time.clock() res = a() zz += time.clock() - start_time print(a()) print((zz)/100, "seconds") zz = 0 for i in range(100000): start_time = time.clock() res = b() zz += time.clock() - start_time print(b()) print((zz)/100, "seconds") 

tratar

  2 in [i for sublist in x for i in sublist] 

Mi código está basado en la solución de Óscar López. Su solución no era exactamente lo que necesitaba para mi problema, pero me dio suficiente información para resolverlo. Por lo tanto, si tiene elementos nesteds en una lista y necesita ver si están en otra lista anidada, esto funcionaría.

 #!python2 lst1 = [['a', '1'], ['b', '2'], ['c', '3'], ['d', '4'], ['e', '5']] lst2 = [['b', '2'], ['d', '4'], ['f', '6'], ['h', '8'], ['j', '10'], ['l', '12'], ['n', '14']] # comparing by index 0, prints lst1 items that aren't in lst2 for i in lst1: if not any(i[0] in sublst for sublst in lst2): print i ''' ['a', '1'] ['c', '3'] ['e', '5'] ''' print # comparing by index 0, prints lst2 items that aren't in lst1 for i in lst2: if not any(i[0] in sublst for sublst in lst1): print i ''' ['f', '6'] ['h', '8'] ['j', '10'] ['l', '12'] ['n', '14'] '''