views:

63

answers:

5

I have a dictionary in Python where the keys are pathnames. For example:

dict["/A"] = 0
dict["/A/B"] = 1
dict["/A/C"] = 1

dict["/X"] = 10
dict["/X/Y"] = 11

I was wondering, what's a good way to print all "subpaths" given any key.

For example, given a function called "print_dict_path" that does this, something like

print_dict_path("/A")

or

print_dict_path("/A/B")

would print out something like:

"B" = 1
"C" = 1

The only method I can think of is something like using regex and going through the entire dictionary, but I'm not sure if that's the best method (nor am I that well versed in regex).

Thanks for any help.

+5  A: 

One possibility without using regex is to just use startswith

top_path = '/A/B'
for p in d.iterkeys():
    if p.startswith(top_path):
        print d[p]
Rakis
+1  A: 

You can use str.find:

def print_dict_path(prefix, d):
    for k in d:
        if k.find(prefix) == 0:
            print "\"{0}\" = {1}".format(k,d[k])
GWW
+1  A: 

Well, you'll definitely have to loop through the entire dict.

def filter_dict_path( d, sub ):
    for key, val in d.iteritems():
        if key.startswith(sub): ## or do you want `sub in key` ?
            yield key, val

print dict(filter_dict_path( old_dict, sub ))

You could speed this up by using the appropriate data structure: a Tree.

THC4k
+1  A: 

Is your dictionary structure fixed? It would be nicer to do this using nested dictionaries:

{
    "A": {
        "value": 0
        "dirs": {
            "B": {
                "value": 1
            }
            "C": {
                "value": 1
            }
        }
    "X": {
        "value": 10
        "dirs": {
            "Y": {
                "value": 11
            }
}

The underlying data structure here is a tree, but Python doesn't have that built in.

katrielalex
You could like to see my post http://stackoverflow.com/questions/3350413/is-there-a-faster-way-to-get-subtrees-from-tree-like-structures-in-python-than-th/3350642#3350642 if you think of tree structure.
Tony Veijalainen
+1  A: 

This removes one level of indenting, which may make the code in the body of the for loop more readable in some cases

top_path = '/A/B'
for p in (p for p in d.iterkeys() if p.startswith(top_path)):
    print d[p]

If you find performance to be a problem, consider using a trie instead of the dictionary

gnibbler