tags:

views:

2113

answers:

6

I have a list and I am appending a dictionary to it as I loop through my data...and I would like to sort by one of the dictionary keys.

ex:

data = "data from database"
list = []
for x in data:
     dict = {'title':title, 'date': x.created_on}
     list.append(dict)

I want to sort the list in reverse order by value of 'date'

+2  A: 

Sort the data (or a copy of the data) directly and build the list of dicts afterwards. Sort using the function sorted with an appropiate key function (operator.attrgetter probably)

Tetha
The key in question is actually operator.itemgetter... this will be much faster than a lamba.
Jarret Hardie
well, if you sort the data-list, its attrgetter, because you need foo.created_on, if you sort the dictionary-list, its itemgetter, because you need foo['date']
Tetha
+10  A: 

You can do it this way:

list.sort(key=lambda item:item['date'], reverse=True)
hvintus
+3  A: 
from operator import itemgetter

your_list.sort(key=itemgetter('date'), reverse=True)

Related notes

  • don't use list, dict as variable names, they are builtin names in Python. It makes your code hard to read.

  • you might need to replace dictionary by tuple or collections.namedtuple or custom struct-like class depending on the context

    from collections import namedtuple
    from operator    import itemgetter
    
    
    Row = namedtuple('Row', 'title date')
    rows = [Row(row.title, row.created_on) for row in data]
    rows.sort(key=itemgetter(1), reverse=True)
    

Example:

>>> lst = [Row('a', 1), Row('b', 2)]
>>> lst.sort(key=itemgetter(1), reverse=True)
>>> lst
[Row(title='b', date=2), Row(title='a', date=1)]

Or

>>> from operator import attrgetter
>>> lst = [Row('a', 1), Row('b', 2)]
>>> lst.sort(key=attrgetter('date'), reverse=True)
>>> lst
[Row(title='b', date=2), Row(title='a', date=1)]

Here's how namedtuple looks inside:

>>> Row = namedtuple('Row', 'title date', verbose=True)

class Row(tuple):
        'Row(title, date)'

        __slots__ = ()

        _fields = ('title', 'date')

        def __new__(cls, title, date):
            return tuple.__new__(cls, (title, date))

        @classmethod
        def _make(cls, iterable, new=tuple.__new__, len=len):
            'Make a new Row object from a sequence or iterable'
            result = new(cls, iterable)
            if len(result) != 2:
                raise TypeError('Expected 2 arguments, got %d' % len(result))
            return result

        def __repr__(self):
            return 'Row(title=%r, date=%r)' % self

        def _asdict(t):
            'Return a new dict which maps field names to their values'
            return {'title': t[0], 'date': t[1]}

        def _replace(self, **kwds):
            'Return a new Row object replacing specified fields with new values'

            result = self._make(map(kwds.pop, ('title', 'date'), self))
            if kwds:
                raise ValueError('Got unexpected field names: %r' % kwds.keys())

            return result

        def __getnewargs__(self):
            return tuple(self)

        title = property(itemgetter(0))
        date = property(itemgetter(1))
J.F. Sebastian
+1  A: 

If you're into the whole brevity thing:

data = "data from database"
sorted_data = sorted(
    [{'title': x.title, 'date': x.created_on} for x in data], 
    key=operator.itemgetter('date'),
    reverse=True)
recursive
That would be key=operator.itemgetter('date') or key=lambda x:x['date']
Stephan202
I don't know what got into my brain there. Fixed.lolz
recursive
`sorted()`returns a new list therefore list comprehension could be replaced by generator expression in your case (replace `[]` by `()`)
J.F. Sebastian
A: 

Thanks for all the great responses.

list.sort(key=lambda item:item['date'], reverse=True)

Worked like a charm!

Also,

@J.F. Sebastian I wasn't using those as variable names, just examples for this post, but thanks for the info.

@Tetha, sorry I should have been more clear, I was doing this proccess multiple times with multiple query's, so I couldn't sort it correctly from the get go.

Joe
Answers are for answers :) Update your question with a new info or leave comments to appropriate answers or both. For example, you could just leave the above comment addressed to me in the comments to my answer.
J.F. Sebastian
A: 

I actually had this almost exact question yesterday and solved it using search. The best answer applied to your question is this:

from operator import itemgetter
list.sort(key=itemgetter('date'), reverse=True)
Dave