44

This is pretty simple but I'd love a pretty, pythonic way of doing it. Basically, given a dictionary, return the subdictionary that contains only those keys that start with a certain string.

» d = {'Apple': 1, 'Banana': 9, 'Carrot': 6, 'Baboon': 3, 'Duck': 8, 'Baby': 2}
» print slice(d, 'Ba')
{'Banana': 9, 'Baby': 2, 'Baboon': 3}

This is fairly simple to do with a function:

def slice(sourcedict, string):
    newdict = {}
    for key in sourcedict.keys():
        if key.startswith(string):
            newdict[key] = sourcedict[key]
    return newdict

But surely there is a nicer, cleverer, more readable solution? Could a generator help here? (I never have enough opportunities to use those).

Aphex
  • 7,390
  • 5
  • 33
  • 54
  • Don't obscure python code just because it is possible. The whole idea of python is readability. If you just need obscure power, use Perl. – user3181121 Sep 01 '15 at 15:04
  • Also see http://pythoncentral.io/how-to-slice-custom-objects-classes-in-python/, you can customize `__getitem__` in your own type/subclass of dict. – bjd2385 Jan 13 '17 at 03:41

3 Answers3

79

How about this:

in python 2.x :

def slicedict(d, s):
    return {k:v for k,v in d.iteritems() if k.startswith(s)}

In python 3.x :

def slicedict(d, s):
    return {k:v for k,v in d.items() if k.startswith(s)}
pranjal thakur
  • 312
  • 2
  • 13
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 3
    Don't shadow the `slice` built-in (even though almost no one uses it). – Ignacio Vazquez-Abrams Dec 30 '10 at 00:12
  • That dict comprehension is delicious. And I had no idea `slice` was a builtin, wtf? – Aphex Dec 30 '10 at 00:19
  • 4
    @Ignacio: When you're in a tiny, local function, it really isn't always worth worrying about stepping on builtins--there are too many of them, with far too common names. Better just to worry about it for nontrivial functions (if that) and globals. Builtins aren't keywords, after all. – Glenn Maynard Dec 30 '10 at 00:24
  • 8
    No dictionary comprehension way `dict((k, v) for k,v in d.iteritems() if k.startswith(s))` – razpeitia Dec 30 '10 at 01:46
  • 2
    in 2017: python can comprehension a dict purely using `in`: `{k:d[k] for k in d if k.startswith(s)}`, no more need to invoke a function call. – cowbert Sep 27 '17 at 18:14
9

In functional style:

dict(filter(lambda item: item[0].startswith(string),sourcedict.iteritems()))

mtpettyp
  • 5,533
  • 1
  • 33
  • 33
seriyPS
  • 6,817
  • 2
  • 25
  • 16
3

In Python 3 use items() instead:

def slicedict(d, s):
    return {k:v for k,v in d.items() if k.startswith(s)}
gc5
  • 9,468
  • 24
  • 90
  • 151