Jeff
Jeff

Reputation: 7210

python list of dictionaries sort multiple keys

I have a list of dictionaries that have keys of path and type (type 0 => file and type 1 => directory) initial looks like this

everything = [{u'path': u'/1/', u'type': 1},
     {u'path': u'/2/', u'type': 1},
     {u'path': u'/3/', u'type': 1},
     {u'path': u'/1/something/a.py', u'type': 0},
     {u'path': u'/1/something/b.py', u'type': 0},
     {u'path': u'/1/something/c.py', u'type': 0},
     {u'path': u'/1/foobar/', u'type': 1},
     {u'path': u'/2/baz/', u'type': 1},
     {u'path': u'/1/something/baz/snap/pop/a.py', u'type': 0},
     {u'path': u'/1/something/baz', u'type': 1}]

I want to first sort on path then off of type so I get something like this

everything = [{u'path': u'/1/', u'type': 1},
     {u'path': u'/1/foobar/', u'type': 1},
     {u'path': u'/1/something/baz', u'type': 1}, # < --- I want this here
     {u'path': u'/1/something/a.py', u'type': 0},
     {u'path': u'/1/something/b.py', u'type': 0},
     {u'path': u'/1/something/baz/snap/pop/a.py', u'type': 0},
     {u'path': u'/1/something/c.py', u'type': 0},
     {u'path': u'/2/', u'type': 1},
     {u'path': u'/2/baz/', u'type': 1},
     {u'path': u'/3/', u'type': 1}]

where the "something" section starts with type 1.

I thought when I do

everything.sort(key=lambda x: (x['path'], x['type']))

I would get what I want, but I get

everything = [{u'path': u'/1/', u'type': 1},
     {u'path': u'/1/foobar/', u'type': 1},
     {u'path': u'/1/something/a.py', u'type': 0},
     {u'path': u'/1/something/b.py', u'type': 0},
     {u'path': u'/1/something/baz', u'type': 1}, # < --- I don't want this here
     {u'path': u'/1/something/baz/snap/pop/a.py', u'type': 0},
     {u'path': u'/1/something/c.py', u'type': 0},
     {u'path': u'/2/', u'type': 1},
     {u'path': u'/2/baz/', u'type': 1},
     {u'path': u'/3/', u'type': 1}]

Is there an easy way to sort everything in this fashion or do I have to write my own sort?

EDIT:

Perhaps this will help explain what I want.

In linux when you do a ls -lR you get a nice list of dirs and files in the dirs listed under it.

Thanks

Upvotes: 0

Views: 609

Answers (2)

khagler
khagler

Reputation: 4056

Your sorting criteria are so esoteric that I think you can only do this by writing a comparison function.

Upvotes: 0

Amber
Amber

Reputation: 526543

You need to only include in the key what you actually want to be sorted. Since you appear to want to reduce the priority of everything after the last slash-delimited segment in the path, you should remove that or move it later in the sort order:

everything.sort(key=lambda x: (
    '/'.join(x['path'].split('/')[:-1]),
    x['type'],
    ''.join(x['path'].split('/')[-1:]),
  )
)

Upvotes: 2

Related Questions