0

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

Jeff
  • 6,932
  • 7
  • 42
  • 72
  • http://wiki.python.org/moin/HowTo/Sorting/ –  Dec 29 '12 at 01:23
  • possible duplicate of [Python sorting list of dictionaries by multiple keys](http://stackoverflow.com/questions/1143671/python-sorting-list-of-dictionaries-by-multiple-keys) – miku Dec 29 '12 at 01:23
  • @miku I saw that but that doesn't do what I want it to do. That's the sort with the key that I have in the post. – Jeff Dec 29 '12 at 01:25
  • @Jeff, sorry, unfortunately I can't undo the close request. – miku Dec 29 '12 at 01:28
  • 1
    @Jeff - how exactly are you wanting to sort? `/1/something/b` comes after `/1/something/a`, but you somehow want things to be the other way only part of the time? You need to define your sort order better. – Amber Dec 29 '12 at 01:35
  • You may want to look at a NamedTuple instead of a dictionary for your data. – xorsyst Feb 28 '13 at 17:40

2 Answers2

2

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:]),
  )
)
Amber
  • 507,862
  • 82
  • 626
  • 550
0

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

khagler
  • 3,996
  • 29
  • 40