dans une simple liste, la vérification suivante est triviale:
x = [1, 2, 3]
2 in x -> True
mais s'il s'agit d'une liste de liste, telle que:
x = [[1, 2, 3], [2, 3, 4]]
2 in x -> False
comment peut-on résoudre ce problème afin de renvoyer True
?
Essayez ceci en utilisant la fonction any
intégrée. C'est la solution la plus idiomatique, mais aussi efficace, car any
court-circuite et s'arrête dès que la première correspondance est trouvée:
x = [[1, 2, 3], [2, 3, 4]]
any(2 in sl for sl in x)
=> True
Voici une version récursive qui fonctionne pour tous les niveaux d'imbrication.
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))
Voici quelques tests:
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
Vous pouvez utiliser set.issubset()
et 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
Vous pouvez également contrôler efficacement l'adhésion de plusieurs éléments:
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
Cela fonctionnerait:
for arr in x:
if 2 in arr:
print True
break
Je recommanderais la réponse d'Oscar, car any
est la bonne option ici.
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))
Notez que, assez intéressant:
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))
Est plus de 50% plus lent à exécuter.
Réponse originale (s)
Que faire si vous avez une profondeur supérieure à 2? Voici une approche du cas générique:
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))
Pas sûr de la vitesse, mais comme je l’ai dit, c’est une approche qui peut être utile à quelqu'un!
MODIFIER - MEILLEURE (PLUS RAPIDE) RÉPONSE:
Cela réduit le temps pris (si n
est trouvé, même si on ne le trouve pas, environ la moitié du temps réellement ...) en revenant plus tôt. Ceci est légèrement plus rapide que la réponse de @Curt F., et plus lent que la création d'une fonction supposant une profondeur maximale de 2 (la réponse acceptée).
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))
Timing rapide (très hacky, désolé, occupé aujourd'hui!):
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")
Mon code est basé sur la solution d'Óscar López. Sa solution n'était pas exactement ce dont j'avais besoin pour résoudre mon problème, mais elle me donnait suffisamment d'informations pour comprendre mon problème. Donc, si vous avez des éléments imbriqués dans une liste et que vous avez besoin de voir s'ils sont dans une autre liste imbriquée, cela fonctionnera.
#!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']
'''
essayer
2 in [i for sublist in x for i in sublist]