2010-04-09 7 views
1

J'ai une liste imbriquée quelque chose comme ceci:Python: Obtenir des objets en profondeur? (? Bibliothèque set)

PLACES = (
    ('CA', 'Canada', (
     ('AB', 'Alberta'), 
     ('BC', 'British Columbia' (
      ('van', 'Vancouver'), 
     ), 
     ... 
    )), 
    ('US', 'United States', (
     ('AL', 'Alabama'), 
     ('AK', 'Alaska'), 
     ... 

J'ai besoin de récupérer des données hors de lui. Si depth est 0 j'ai besoin de récupérer tous les pays (et leurs codes), si depth == 1, j'ai besoin de récupérer tous les états/provinces, si depth == 2 j'ai besoin de récupérer toutes les villes ... et ainsi de suite. Y a-t-il une bibliothèque pour faire des trucs comme ça? Ou quelqu'un peut me pointer dans la bonne direction? J'ai commencé à coder une solution seulement pour réaliser qu'elle ne fonctionnerait pas pour des niveaux plus profonds que 1 parce que vous devez entrer et sortir de chaque liste ...

Notez également que tous les éléments n'ont pas une 3ème partie (c.-à-d. nous prétendons que l'Alberta n'a pas de villes, donc récupérer des objets en profondeur 2 reviendrait à ('van','Vancouver') dans ce scénario limité). Je n'avais pas réalisé cela avant, mais j'avais aussi besoin de la valeur parente. Donc, j'ai modifié la solution de interjay:

def depth_gen(seq, depth, par=None): 
    if depth==0: 
     for x in seq: 
      yield par, x[0], x[1] 
     return 

    for x in seq: 
     if len(x)==3: 
      par = x[0] 
      for y in depth_gen(x[2], depth-1, par): 
       yield y 

qui j'utilise pour générer du code HTML:

<label for="id-pickup_address-province">Province</label> 
<select id="id-pickup_address-province" rel="pickup_address-country" name="pickup_address-province"> 
    <option rel="CA" value="AB">Alberta</option> 
    <option rel="CA" value="BC">British Columbia</option> 
    <option rel="CA" value="MB">Manitoba</option> 
    ... 
    <option rel="US" value="WV">West Virginia</option> 
    <option rel="US" value="WI">Wisconsin</option> 
    <option rel="US" value="WY">Wyoming</option> 
</select> 
<label for="id-pickup_address-country">Country</label> 
<select id="id-pickup_address-country" name="pickup_address-country"> 
    <option value="CA">Canada</option> 
    <option value="US">United States</option> 
</select> 

Et alors je devrais être en mesure de filtrer facilement la liste avec jQuery basée sur quel pays est sélectionné ...

+0

votre question est un peu déroutant. Qu'entendez-vous par "profondeur", c'est à quelle profondeur dans le tuple de tuples que vous voulez extraire? – wheaties

+0

@wheaties: Oui ... profondeur = 0 est le premier niveau (tous les pays), profondeur = 1 est le deuxième niveau (tous les états), etc. Appelez-le comme vous voulez, mais je dois être en mesure de récupérer les éléments basés sur la profondeur de leur imbrication. – mpen

Répondre

5

Voici une solution qui fonctionnera pour toute profondeur:

def depthGenerator(seq, depth): 
    if depth==0: 
     for x in seq: 
      yield x[:2] #strip subsequences 
     return 

    for x in seq: 
     if len(x)==3: #has subsequence? 
      for y in depthGenerator(x[2], depth-1): 
       yield y 

Exemple:

>>> list(depthGenerator(PLACES, 1)) 
[('AB', 'Alberta'), ('BC', 'British Columbia'), ('AL', 'Alabama'), ('AK', 'Alaska')] 
+0

Cela semble beaucoup plus élégant et fonctionnel que ce que je travaillais sur! – mpen

1

Voici ce que je vois:

for (county, countryName, stateTuple) in MyTuple: 
    for (state, stateName, CountyTuple) in stateTuple: 
     ... 

et ainsi de suite, ce qui est un motif répétitif.

def extract(myTuple, level): 
    if level: 
     return (item[2] for item in myTuple if len(item) == 3) 
    else: 
     return ((item[0], item[1]) for item in myTuple) 

Puis appelez l'extrait autant de fois que nécessaire pour votre "profondeur".

1

Suggestion, n'utilisez pas les listes imbriquées. Créer une sorte de structure réelle des classes qui vous donne plus d'informations et d'organisation. Il sera plus facile de réfléchir, plus facile à coder et plus facile à lire pour les autres.

+0

Je vais pour la facilité de création. Cela se passe dans un cadre, et je veux que les gens puissent écrire leurs choix rapidement sans aucun superflu. – mpen

+0

(Merci pour la suggestion si!) – mpen

Questions connexes