C'est assez différent de ce que j'ai trouvé dans de nombreux threads - je ne veux pas rendre la liste plate mais les niveaux non imbriqués comme suit:
[[[3, 3]]] devrait être [3, 3]
[[[3, 4], [3, 3]]] doit être [[3, 4], [3, 3]] mais pas [3, 4], [3, 3] ni [3, 4, 3, 3] car cela change complètement la structure.
Fondamentalement, je voulais réduire les niveaux pour obtenir le même len (a_list) dans la première et la deuxième itération avant la rupture de boucle. Mais mon idée est quelque peu fausse:
Ce code fonctionne pour tout sauf [[3], [4]] . Je ne sais pas ce qui ne va pas aujourd'hui parce que cela a fonctionné hier. Besoin d'aide pour corriger cette fonction. Maintenant, il renvoie [3] mais devrait rester inchangé.
# Unlevel list - reduce unnecessary nesting without changing nested lists structure
def unlevelList(l):
if len(l) > 0 and isinstance(l, list):
done = True
while done == True:
if isinstance(l[0], list):
if len(l) == len(l[0]):
l = l[0]
else:
l = l[0]
done = False
else:
done = False
return l
else:
return l
3 Réponses :
Je serais enclin à le faire avec la récursivité: si l'objet est une liste de longueur 1, enlevez le calque extérieur; puis, annulez récursivement le niveau de tous ses enfants.
When [[[3, 3]]] is unleveled, it becomes [3, 3] When [[[3, 4], [3, 3]]] is unleveled, it becomes [[3, 4], [3, 3]] When [[3], [4]] is unleveled, it becomes [[3], [4]] When [[[3]]] is unleveled, it becomes 3 When [[[3], [3, 3]]] is unleveled, it becomes [[3], [3, 3]]
Résultat:
def unlevel(obj):
while isinstance(obj, list) and len(obj) == 1:
obj = obj[0]
return obj
test_cases = [
[[[3, 3]]],
[[[3, 4], [3, 3]]],
[[3], [4]],
[[[3]]],
[[[3], [3, 3]]]
]
for x in test_cases:
print("When {} is unleveled, it becomes {}".format(x, unlevel(x)))
Edit: relisant votre question, je pense peut-être vous voulez que [[3], [4]] reste [[3], [4]] . Si tel est le cas, alors j'interprète les exigences comme étant "seulement enlever les crochets excédentaires de la couche supérieure; laisser les listes intérieures à un élément inchangées". Dans ce cas, vous n'avez pas besoin de récursivité. Supprimez simplement la liste du haut jusqu'à ce que vous n'en puissiez plus, puis renvoyez-la.
When [[[3, 3]]] is unleveled, it becomes [3, 3] When [[[3, 4], [3, 3]]] is unleveled, it becomes [[3, 4], [3, 3]] When [[3], [4]] is unleveled, it becomes [3, 4] When [[[3]]] is unleveled, it becomes 3 When [[[3], [3, 3]]] is unleveled, it becomes [3, [3, 3]]
Résultat:
def unlevel(obj):
while isinstance(obj, list) and len(obj) == 1:
obj = obj[0]
if isinstance(obj, list):
return [unlevel(item) for item in obj]
else:
return obj
test_cases = [
[[[3, 3]]],
[[[3, 4], [3, 3]]],
[[3], [4]],
[[[3]]],
[[[3], [3, 3]]]
]
for x in test_cases:
print("When {} is unleveled, it becomes {}".format(x, unlevel(x)))
p >
Cela redéfinit incorrectement [[[3], [3, 3]]] en [3, [3, 3]] , où je crois [[3 ], [3, 3]] est attendu.
@blhsing Je pense que vous avez raison. J'ai ajouté une approche supplémentaire.
Honnêtement pas mal. Ce "supports excédentaires uniquement" était ce que je recherchais. Merci pour 2 versions.
Ceci est fait mais je ne peux pas changer [[[[4]]]] pour obtenir une liste toujours. Donc, à la place, 4 veut avoir [4] .
Hmm, vous pourriez peut-être changer la dernière ligne en return obj if isinstance (obj, list) else [obj] . La réponse de Nathan garantit également que le résultat est une liste.
Je recommande également une solution récursive
[[3], [3, 3]] [3, 3] [[3, 4], [3, 3]] [[3], [4]] [3]
Certains cas de test
test_cases = [
[[[3], [3, 3]]],
[[[3, 3]]],
[[[3, 4], [3, 3]]],
[[3], [4]],
[[[3]]]
]
for i in test_cases:
print(unnest(i))
donne
def unnest(l):
if isinstance(l, list) and len(l) == 1 and isinstance(l[0], list):
return unnest(l[0])
return l
Ce code semble faire exactement ce que vous voulez. Conservez les listes sous forme de listes (mais plates).
import itertools
a = [[[[1, 2]]], [[2, 3, 4, 5]], [[[[[[134, 56]]]]]], 9, 8, 0]
res = []
for element in a:
if isinstance(element, list):
while len(element) == 1:
element = list(itertools.chain(*element))
res.append(element)
else:
res.append(element)
print(res)
Avec le résultat res étant [[1, 2], [2, 3, 4, 5], [134, 56], 9, 8, 0]
Pas exactement ce que je cherchais (ne pas enlever les nids internes) mais c'est utile aussi.
Je pense que votre implémentation rencontrera des problèmes si vos sous-listes sont de tailles différentes, c'est-à-dire si votre structure de données n'est pas rectangulaire.