Extraire toutes les combinaison d'un chemin

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous,

J’aurai besoin de votre aide pour un petit script :
j’ai une chaine de caractère qui ressemble à un chemin de répertoire (donc des chaines séparées par "/")
exemple : 'le site/zestedesavoir/est super'

Je cherche à récupérer toutes les combinaisons de cette chaine de manière ordonnée et avec au moins toujours le dernier élément.
ici on aurait :

['le site', 'zestedesavoir', 'est super']
['le site', 'est super']
['est super']
['zestedesavoir', 'est super']

la longueur de la chaine peut varier.

J’ai donc pensé utiliser itertools.combinations mais cela m’oblige à l’utiliser autant de fois qu’il y a d’éléments dans ma liste

import itertools
s = 'le site/zestedesavoir/est super'.split('/')
all_combinations = []
for i in range(len(s)):
    combination = itertools.combinations(s, i +1)
    all_combinations += list(combination)

for combination in all_combinations:
    if s[-1] == combination[-1]: # on veut uniquement les combinaisons qui se finisse par le dernier élément de la chaine
        print(combination)

cela fonctionne mais je me demande si c’est optimal ?

+0 -0

Bonjour,

Pour générer toutes les combinaisons, tu peux pour cela utiliser une fonction récursive. Et tu construis au fur et à mesure ton résultat r (et tu réduis la taille de ton entrée t), en faisant deux appels récursif (l’un ou l’élément courant est ajouté au résultat, l’un ou l’autre ne l’est pas).

étape 0 : t = ['le site', 'zestedesavoir'], r = []
  étape 1.1 : t = ['zestedesavoir'], r = ['le site']
    étape 2.1 : t = [], r = ['le site', 'zestedesavoir'] -> t est vide j’ajoute r au résultat
    étape 2.2 : t = [], r = ['le site'] -> t est vide, j’ajoute r au résultat
  étape 1.2 : t = ['zestedesavoir'], r = []
    étape 2.1 : t = [], r = ['zestedesavoir'] -> t est vide [...]
    étape 2.2 : t = [], r = [] -> t est vide [...]

De cette manière tu peux générer toutes les combinaisons possibles (c’est généralisable avec un tableau de taille arbitraire, puisque fonction récursive).

C’est peut être un peu plus efficace que itertools mais ce n’est vraiment pas certain, je laisse d’autres (plus avertis) t’éclairer sur ce point.

+0 -0

cela fonctionne mais je me demande si c’est optimal ?

Je ne pense pas. En fait si tu veux toujours le dernier élément à la fin il te suffit de générer les combinaisons sans considérer ce dernier et l’ajouter manuellement ensuite. Sinon je crois qu’il vaut mieux utiliser la méthode extend pour concaténer des listes plutôt que d’en construire une nouvelle avec +=.

Ma proposition :

import itertools

*path_parts, path_end = 'le site/zestedesavoir/est super'.split('/')

all_path_combinations = []
for i in range(len(path_parts) + 1):
    combination = itertools.combinations(path_parts, i)
    all_path_combinations.extend([(*comb, path_end ) for comb in combination])

print(all_path_combinations)

Edit: Du coup je suis un peu redondant mais bon :p

+1 -0

Sinon je crois qu’il vaut mieux utiliser la méthode extend pour concaténer des listes plutôt que d’en construire une nouvelle avec +=.

Ma proposition :

all_path_combinations.extend([(*comb, path_end ) for comb in combination])

simbilou

L’avantage d'extend est justement que tu n’as pas besoin de construire une liste pour le rhs puisqu’elle peut prendre un itérable (donc un générateur) :

all_path_combinations.extend((*comb, path_end) for comb in combination)

(+= ne crée pas de nouvelle liste par ailleurs, le lhs est modifié directement).

@DonKnacki : je vois le tag Python 2, à moins de maintenir un vieux code dont la migration vers Python 3 serait vraiment compliquée, utilise Python 3. Python 2 est en fin de vie, et Python 3 apporte pas mal de choses.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte