Reputation: 1482
Working with a path-based resource system, the application needs to find the first working resource that manages a given resource based on paths. I need a succinct, pythonic way to generate the following:
Input:
/house/dogs/ralph/bone
Output:
/house/dogs/ralph/bone
/house/dogs/ralph
/house/dogs
/house
Note: It's okay to use os.path
or similar built-ins, but these are not filesystem resources. Output can be anything iterable (list, set, generator, etc.).
Upvotes: 4
Views: 2272
Reputation: 114440
Use pathlib
. PurePath
s offer an abstract interface to path-like objects that have no relationship to the file system. In particular, PurePosixPath
is the kind that uses forward slashes (/
) as separators:
>>> from pathlib import PurePosixPath
>>> p = PurePosixPath('/house/dogs/ralph/bone')
>>> str(p.parent)
/house/dogs/ralph
>>> str(p.parent.parent)
/house/dogs
You can loop this easily:
p = PurePosixPath(...)
while str(p) != p.root:
# Do stuff to p
p = p.parent
A fairly pythonic finishing touch would be to make it a generator:
def receding_path(p):
p = PurePosixPath(p)
while str(p) != p.root:
yield str(p)
p = p.parent
for item in receding_path('/house/dogs/ralph/bone'):
# do stuff to each item
Upvotes: 6
Reputation: 6623
Something of a combination of the previous two answers:
import pathlib
import os
def resources(path):
parts = pathlib.Path(path).parts
for n in range(len(parts), 1, -1):
yield os.path.join(*parts[:n])
Upvotes: 2
Reputation: 43524
One way would be to split the string on "/"
and take successive slices.
in_string = "/house/dogs/ralph/bone"
s = in_string.split("/")
out_strings = list(filter(None, ("/".join(s[:i+1]) for i in range(len(s)))))
print(out_strings)
#['/house', '/house/dogs', '/house/dogs/ralph', '/house/dogs/ralph/bone']
The filter(None, ...)
is used to remove empty strings.
Or reverse the range if you want the output in the order you specified in your post:
out_strings = list(filter(None, ("/".join(s[:i]) for i in range(len(s), 0, -1))))
print(out_strings)
#['/house/dogs/ralph/bone',
# '/house/dogs/ralph',
# '/house/dogs',
# '/house']
Upvotes: 1