С учетом
>>> import pathlib
>>> import itertools as it
>>> base = ["/a", "/b"]
>>> subdirs = [["1", "2"], ["c", "d"]]
Рецепт вспомогательных itertools:
>>> def powerset(iterable):
... "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
... s = list(iterable)
... return it.chain.from_iterable(it.combinations(s, r) for r in range(len(s)+1))
Код
>>> def subsequence(iterable, pred=None):
... """Return a non-contiguous subsequence."""
... if pred is None: pred = lambda x: x
... return (x for x in powerset(iterable) if x and pred(x))
>>> prods = list(it.product(base, subdirs[0], subdirs[1]))
>>> pred = lambda x: x[0].startswith("/")
>>> result = sorted(set(it.chain.from_iterable(subsequence(p, pred) for p in prods)))
>>> result
[('/a',),
('/a', '1'),
('/a', '1', 'c'),
('/a', '1', 'd'),
('/a', '2'),
('/a', '2', 'c'),
('/a', '2', 'd'),
('/a', 'c'),
('/a', 'd'),
('/b',),
('/b', '1'),
('/b', '1', 'c'),
('/b', '1', 'd'),
('/b', '2'),
('/b', '2', 'c'),
('/b', '2', 'd'),
('/b', 'c'),
('/b', 'd')]
Приложения
Объединение путей в виде строк или pathlib
объектов.
>>> ["/".join(x) for x in result];
['/a', '/a/1', '/a/1/c', ...]
>>> [pathlib.Path(*x) for x in result];
[WindowsPath('/a'), WindowsPath('/a/1'), WindowsPath('/a/1/c'), ...]
информация
Steps
prods
- это все itertools.product
с , которые принимают итерации и создают уникальные комбинации (или декартовы произведения) способом, аналогичным диалоговому приложению выбора даты . См. Примеры ниже.
subsequence
- это просто оболочка рецепта powerset
itertools . Это позволяет использовать pred
icate, который используется для фильтрации результатов, начинающихся с косых черт, таких как base
.
result
сортирует уплощенный набор подпоследовательностей, сгенерированных для каждого продукта. При желании вы можете присоединиться к каждому элементу. См. Код - Приложения.
Примеры
Вот декартовы произведения:
>>> prods
[('/a', '1', 'c'),
('/a', '1', 'd'),
('/a', '2', 'c'),
('/a', '2', 'd'),
('/b', '1', 'c'),
('/b', '1', 'd'),
('/b', '2', 'c'),
('/b', '2', 'd')]
Без предиката допускаются нежелательные подпоследовательности:
>>> list(subsequence(prods[0]))
[('/a',),
('1',), # bad
('c',),
('/a', '1'),
('/a', 'c'),
('1', 'c' # bad
('/a', '1', 'c')]
Таким образом, мы фильтруем нежелательные элементы с помощью предиката, pred
.
>>> list(subsequence(prods[0], pred=pred))
[('/a',), ('/a', '1'), ('/a', 'c'), ('/a', '1', 'c')]