2013-07-19 3 views
2

Quelle est la meilleure façon de convertir les éléments suivants:modification de la structure de la liste Python

myList = [ 
      ['ItemB','ItemZ'], 
      ['ItemB','ItemP'], 
      ['ItemB','ItemJ','Item6'], 
      ['ItemB','ItemJ','Item5'] 
     ] 

ce en Python:

newList = ['ItemB',['ItemP','ItemZ',['ItemJ',['Item5','Item6']]]] 

J'ai pu se rapprocher en utilisant une fonction récursive qui triée par Len mais ne pouvait pas trouver un bon moyen de trier par Len puis par ordre alphabétique. Toute aide serait grandement appréciée!

+9

S'il vous plaît ne hésitez pas à partager votre * J'ai pu approcher à l'aide d'une fonction récursive * –

+0

Les deux listes semblent identiques, à mes yeux. Qu'est-ce que je rate? –

+0

C'est un dictionnaire que vous voulez, mon ami. – 2rs2ts

Répondre

1

Peut-être pas la manière la plus élégante, mais cela semble fonctionner:

D'abord, nous nous tournons la liste des listes dans un dictionnaire en utilisant un defaultdict de defaultdicts de defaultdicts, alias infinitedict

myList = [['ItemB','ItemZ'],['ItemB','ItemP'],['ItemB','ItemJ','Item6'],['ItemB','ItemJ','Item5']] 

from collections import defaultdict 
infinitedict = lambda: defaultdict(infinitedict) 
dictionary = infinitedict() 
for item in myList: 
    d = dictionary 
    for i in item: 
     d = d[i] 

maintenant , nous pouvons utiliser une fonction récursive pour transformer ce dictionnaire en une liste arborescente:

def to_list(d): 
    lst = [] 
    for i in d: 
     lst.append(i) 
     if d[i]: 
      lst.append(to_list(d[i])) 
    return lst 

La sortie est un peu différent de votre résultat attendu, mais cela semble plus logique pour moi:

>>> print to_list(dictionary) 
['ItemB', ['ItemZ', 'ItemJ', ['Item6', 'Item5'], 'ItemP']] 

Ou, plus près de votre résultat attendu (mais toujours pas exactement la même chose, que l'ordre est escalada en raison de l'étape intermédiaire avec le dictionnaire) en utilisant ceci:

def to_list(d): 
    return [[i] + [to_list(d[i])] if d[i] else i for i in d] 

sortie:

>>> print to_list(dictionary)[0] 
['ItemB', ['ItemZ', ['ItemJ', ['Item6', 'Item5']], 'ItemP']] 
+0

Si vous pouvez l'obtenir pour être '['ItemB', ['ItemZ', ['ItemJ', ['Item6', 'Item5']], 'ItemP']]' ce sera ce que l'OP veut. – 2rs2ts

1

similaires à la réponse de tobias_k, mais dans le format que vous voulez, Sorte d et tous. (je pense.) D'accord, il a été testé et semble fonctionner maintenant.

Nous transformons la liste de chemins en arborescence avec defaultdict, puis transformons récursivement l'arborescence defaultdict en une liste triée.

from collections import defaultdict 

def tree(): 
    # A dict-based tree that automatically creates nodes when you access them. 
    # Note that this does not store a name for itself; it's closer to a dropdown 
    # menu than the little button you click to display the menu, or the contents 
    # of a directory rather than the directory itself. 
    return defaultdict(tree) 

def paths_to_tree(paths): 
    # Make a tree representing the menu. 
    menu = tree() 
    for path in myList: 
     add_to = menu 

     # Traverse the tree to automatically create new tree nodes. 
     for name in path: 
      add_to = add_to[name] 
    return menu 

def sort_key(item): 
    if isinstance(item, list): 
     return 1, item[0] 
    else: 
     # It's a string 
     return 0, item 

# Recursively turn the tree into nested lists. 
def tree_to_lists(menu): 
    lists = [[item, tree_to_lists(menu[item])] if menu[item] else item 
      for item in menu] 
    lists.sort(key=sort_key) 
    return lists 

# Note the [0]. 
output = tree_to_lists(paths_to_tree(myList))[0] 
Questions connexes