2010-03-29 4 views
2

Je sais que c'est très similaires à quelques autres questions, mais je ne peux pas vraiment obtenir cette fonction pour fonctionner correctement.Convertir les arguments en liste à plat?

def flatten(*args): 
    return list(item for iterable in args for item in iterable) 

La sortie Je cherche est:

flatten(1) -> [1] 
flatten(1,[2]) -> [1, 2] 
flatten([1,[2]]) -> [1, 2] 

La fonction actuelle, que je pris d'une autre réponse SO, ne semble pas produire des résultats corrects du tout:

>>> flatten([1,[2]]) 
[1, [2]] 
+1

Postez votre solution en guise de réponse et acceptez celle-ci. Garder le site propre :) – Powertieke

+0

J'ai mis à jour ma réponse, aussi - votre réponse trouvée était un peu plus propre. ;) –

Répondre

6

Pour une solution rapide, il suffit de prendre votre deuxième fonction et la rendre récursive.

def flatten(*args): 
    output = [] 
    for arg in args: 
     if hasattr(arg, '__iter__'): 
      output.extend(flatten(*arg)) 
     else: 
      output.append(arg) 
    return output 
+0

test __iter__ ne fonctionne pas pour hash, donc: –

+0

Exemple de résultats de dictionnaire étranges: >>> def aplatissent (* args): ... Sortie = [] ... pour arg args : ... si hasattr (arg, '__iter__'): ... output.extend (aplatissent (* arg)) ... autre: ... output.append (arg) ... retour sortie ... >>> adict = {1: 2, 3: 4, 5: 6} >>> blist = ['a', 'b', 'c'] >>> raw = [ adict, blist] >>> aplatir (cru) [1, 3, 5, 'a', 'b', 'c'] –

+0

itération ove r un dictionnaire donne ses clés. Puisque la question d'origine ne disait rien de la sortie désirée pour les dictionnaires, pourquoi cette sortie est-elle étrange? –

4

Si vous voulez aplatir les listes arbitrairement imbriquées vous avez besoin d'une fonction récursive:

def flatten(ls): 
    if isinstance(ls, list): 
    return [fa for a in ls for fa in flatten(a)] 
    else: 
    return [ls] 

(Si vous prévoyez d'aplatir les grandes structures cela pourrait être rendu plus efficace en utilisant des générateurs au lieu des listes de retour.)

Cette fonction peut également être réutilisée pour créer une fonction qui prend plusieurs paramètres:

def pflatten(*ls): 
    return flatten(list(ls)) 
+0

L'argument d'entrée doit être '* ls'. Cela fait une différence, n'est-ce pas? Et 'hasattr (a, '__iter __')' est légèrement plus polyvalent que 'isinstance' n'est-ce pas? – mpen

+0

@Mark: Actuellement, la fonction prend un argument, et si c'est une liste, elle l'aplatit. Cela peut aussi être fait avec '* ls', de sorte que la fonction prenne plusieurs paramètres et crée une liste plate de leurs concaténations. Quelle interface vous préférez est juste une question de goût, je dirais. Similaire pour 'isinstance (a, list)' contre'hasattr (a, '__iter __')': Cela dépend du type de résultat que vous voulez quand vous lui donnez une liste de listes d'ensembles. Une liste d'ensembles ou une liste de tous les éléments dans tous les ensembles? Selon vos besoins, l'un ou l'autre serait préférable. – sth

+0

Eh bien oui, mais cette question concernait spécifiquement ce dernier ('* ls'). Je vois votre point de vue sur les ensembles bien que ... ne planifie pas d'utiliser ceux-ci, mais les tuples devraient certainement être convertis en une liste plate. – mpen

-1

résolu le problème ...

def flatlist(*args): 
    lst = [] 
    for a in args: 
     if hasattr(a, '__iter__'): lst.extend(flatlist(*a)) 
     else: lst.append(a) 
    return lst 
1

Vérification __ __ iter présence peut être assez étrange quand aplatissement dictionnaire:

>>> def flatten(*args): 
...  output = [] 
...  for arg in args: 
...   if hasattr(arg, '__iter__'): 
...    output.extend(flatten(*arg)) 
...   else: 
...    output.append(arg) 
...  return output 
... 
>>> adict = {1:2, 3:4, 5:6} 
>>> blist = ['a', 'b', 'c'] 
>>> raw = [adict, blist] 
>>> flatten(raw) 
[1, 3, 5, 'a', 'b', 'c'] 

Je pense que aplatissent devrait fonctionner pour les listes et tuples seulement:

import types 

def flatten(*args): 
    output = [] 
    for arg in args: 
     if isinstance(arg, (types.ListType, types.TupleType)): 
      output.extend(flatten(*list(arg))) 
     else: 
      output.append(arg) 
    return output 

adict = {1:2, 3:4, 5:6} 
blist = ['a', 'b', 'c'] 
raw = [adict, blist] 
print flatten(raw) 
Questions connexes