Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #86766 > unrolled thread

Sort list of dictionaries

Started byCharles Heizer <ceh329@gmail.com>
First post2015-03-02 10:17 -0800
Last post2015-03-03 18:55 +1100
Articles 16 — 9 participants

Back to article view | Back to comp.lang.python


Contents

  Sort list of dictionaries Charles Heizer <ceh329@gmail.com> - 2015-03-02 10:17 -0800
    Re: Sort list of dictionaries Emile van Sebille <emile@fenx.com> - 2015-03-02 10:31 -0800
      Re: Sort list of dictionaries Charles Heizer <ceh329@gmail.com> - 2015-03-02 10:38 -0800
        Re: Sort list of dictionaries Ian Kelly <ian.g.kelly@gmail.com> - 2015-03-02 11:55 -0700
        Re: Sort list of dictionaries Charles Heizer <ceh329@gmail.com> - 2015-03-02 10:58 -0800
          Re: Sort list of dictionaries Peter Otten <__peter__@web.de> - 2015-03-02 20:23 +0100
            Re: Sort list of dictionaries Charles Heizer <ceh329@gmail.com> - 2015-03-03 07:56 -0800
              Re: Sort list of dictionaries Chris Angelico <rosuav@gmail.com> - 2015-03-04 03:09 +1100
                Re: Sort list of dictionaries Paul  Moore <p.f.moore@gmail.com> - 2015-03-03 08:48 -0800
              Re: Sort list of dictionaries Peter Otten <__peter__@web.de> - 2015-03-03 18:44 +0100
        Re: Sort list of dictionaries Dave Angel <davea@davea.name> - 2015-03-02 13:59 -0500
        Re: Sort list of dictionaries Jason Friedman <jsf80238@gmail.com> - 2015-03-02 22:33 -0700
        Re: Sort list of dictionaries Chris Angelico <rosuav@gmail.com> - 2015-03-03 18:07 +1100
        Re: Sort list of dictionaries Jason Friedman <jsf80238@gmail.com> - 2015-03-03 07:45 -0700
        Re: Sort list of dictionaries Chris Angelico <rosuav@gmail.com> - 2015-03-04 01:50 +1100
    Re: Sort list of dictionaries Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-03-03 18:55 +1100

#86766 — Sort list of dictionaries

FromCharles Heizer <ceh329@gmail.com>
Date2015-03-02 10:17 -0800
SubjectSort list of dictionaries
Message-ID<f1a339d0-0386-43ba-b6b4-1aee39d75581@googlegroups.com>
Hello,
I'm new to python and I'm trying to find the right way to solve this issue I have.

I'm trying to sort this list by name and then by version numbers. The problem I'm having is that I can not get the version numbers sorted with the highest at the top or sorted properly. 

mylist = [{'name': u'com.google.earth', 'version': u'7.1.2.2041'},
{'name': u'com.google.earth', 'version': u'7.1.2.2019'},
{'name': u'com.google.Chrome', 'version': u'40.0.2214.93'},
{'name': u'com.google.Chrome', 'version': u'40.0.2214.91'},
{'name': u'com.google.Chrome', 'version': u'40.0.2214.111'},
{'name': u'com.google.Chrome', 'version': u'39.0.2171.99'},
{'name': u'com.google.Chrome', 'version': u'39.0.2171.95'},
{'name': u'com.google.Chrome', 'version': u'39.0.2171.71'},
{'name': u'com.google.Chrome', 'version': u'38.0.2125.122'},
{'name': u'com.google.Chrome', 'version': u'38.0.2125.111'},
{'name': u'com.google.Chrome', 'version': u'38.0.2125.104'},
{'name': u'com.google.Chrome', 'version': u'38.0.2125.101'},
{'name': u'com.google.Chrome', 'version': u'37.0.2062.94'},
{'name': u'com.google.Chrome', 'version': u'37.0.2062.120'},
{'name': u'com.google.Chrome', 'version': u'36.0.1985.143'},
{'name': u'com.google.Chrome', 'version': u'36.0.1985.125'},
{'name': u'com.google.Chrome', 'version': u'35.0.1916.153'},
{'name': u'com.google.Chrome', 'version': u'35.0.1916.114'},
{'name': u'com.google.Chrome', 'version': u'34.0.1847.137'},
{'name': u'com.google.Chrome', 'version': u'34.0.1847.131'},
{'name': u'com.google.Chrome', 'version': u'34.0.1847.116'},
{'name': u'com.google.Chrome', 'version': u'33.0.1750.152'},
{'name': u'com.google.Chrome', 'version': u'33.0.1750.149'},
{'name': u'com.google.Chrome', 'version': u'33.0.1750.146'},
{'name': u'com.google.Chrome', 'version': u'32.0.1700.107'},
{'name': u'com.google.Chrome', 'version': u'31.0.1650.63'},
{'name': u'com.google.Chrome', 'version': u'31.0.1650.57'}]

sortedlist = sorted(mylist , key=lambda x, y: x['name'] LooseVersion(elem['version'])), reverse=True)

Thanks,
Charlie

[toc] | [next] | [standalone]


#86767

FromEmile van Sebille <emile@fenx.com>
Date2015-03-02 10:31 -0800
Message-ID<mailman.56.1425321135.13471.python-list@python.org>
In reply to#86766
On 3/2/2015 10:17 AM, Charles Heizer wrote:
> Hello,
> I'm new to python and I'm trying to find the right way to solve this issue I have.
>
> I'm trying to sort this list by name and then by version numbers. The problem I'm having is that I can not get the version numbers sorted with the highest at the top or sorted properly.
>
> mylist = [{'name': u'com.google.earth', 'version': u'7.1.2.2041'},
> {'name': u'com.google.earth', 'version': u'7.1.2.2019'},
> {'name': u'com.google.Chrome', 'version': u'40.0.2214.93'},
> {'name': u'com.google.Chrome', 'version': u'40.0.2214.91'},
> {'name': u'com.google.Chrome', 'version': u'40.0.2214.111'},
> {'name': u'com.google.Chrome', 'version': u'39.0.2171.99'},
> {'name': u'com.google.Chrome', 'version': u'39.0.2171.95'},
> {'name': u'com.google.Chrome', 'version': u'39.0.2171.71'},
> {'name': u'com.google.Chrome', 'version': u'38.0.2125.122'},
> {'name': u'com.google.Chrome', 'version': u'38.0.2125.111'},
> {'name': u'com.google.Chrome', 'version': u'38.0.2125.104'},
> {'name': u'com.google.Chrome', 'version': u'38.0.2125.101'},
> {'name': u'com.google.Chrome', 'version': u'37.0.2062.94'},
> {'name': u'com.google.Chrome', 'version': u'37.0.2062.120'},
> {'name': u'com.google.Chrome', 'version': u'36.0.1985.143'},
> {'name': u'com.google.Chrome', 'version': u'36.0.1985.125'},
> {'name': u'com.google.Chrome', 'version': u'35.0.1916.153'},
> {'name': u'com.google.Chrome', 'version': u'35.0.1916.114'},
> {'name': u'com.google.Chrome', 'version': u'34.0.1847.137'},
> {'name': u'com.google.Chrome', 'version': u'34.0.1847.131'},
> {'name': u'com.google.Chrome', 'version': u'34.0.1847.116'},
> {'name': u'com.google.Chrome', 'version': u'33.0.1750.152'},
> {'name': u'com.google.Chrome', 'version': u'33.0.1750.149'},
> {'name': u'com.google.Chrome', 'version': u'33.0.1750.146'},
> {'name': u'com.google.Chrome', 'version': u'32.0.1700.107'},
> {'name': u'com.google.Chrome', 'version': u'31.0.1650.63'},
> {'name': u'com.google.Chrome', 'version': u'31.0.1650.57'}]
>
> sortedlist = sorted(mylist , key=lambda x, y: x['name'] LooseVersion(elem['version'])), reverse=True)

You'll need to fix LooseVersion or elem or both -- or show them so we 
can help.

Emile



>
> Thanks,
> Charlie
>

[toc] | [prev] | [next] | [standalone]


#86768

FromCharles Heizer <ceh329@gmail.com>
Date2015-03-02 10:38 -0800
Message-ID<946797be-10e6-433b-9411-2db0d5697ac8@googlegroups.com>
In reply to#86767
Sorry,

sortedlist = sorted(mylist , key=lambda elem: "%s %s" % (elem['name'], LooseVersion(elem['version'])), reverse=True)

This is what I was trying but LooseVersion() was not sorting version numbers like I thought it would. You will notice that Chrome version "40.0.2214.111" is higher than "40.0.2214.91" but in the end result it's not sorting it that way.

Thanks,
Charlie

On Monday, March 2, 2015 at 10:32:40 AM UTC-8, Emile van Sebille wrote:
> On 3/2/2015 10:17 AM, Charles Heizer wrote:
> > Hello,
> > I'm new to python and I'm trying to find the right way to solve this issue I have.
> >
> > I'm trying to sort this list by name and then by version numbers. The problem I'm having is that I can not get the version numbers sorted with the highest at the top or sorted properly.
> >
> > mylist = [{'name': u'com.google.earth', 'version': u'7.1.2.2041'},
> > {'name': u'com.google.earth', 'version': u'7.1.2.2019'},
> > {'name': u'com.google.Chrome', 'version': u'40.0.2214.93'},
> > {'name': u'com.google.Chrome', 'version': u'40.0.2214.91'},
> > {'name': u'com.google.Chrome', 'version': u'40.0.2214.111'},
> > {'name': u'com.google.Chrome', 'version': u'39.0.2171.99'},
> > {'name': u'com.google.Chrome', 'version': u'39.0.2171.95'},
> > {'name': u'com.google.Chrome', 'version': u'39.0.2171.71'},
> > {'name': u'com.google.Chrome', 'version': u'38.0.2125.122'},
> > {'name': u'com.google.Chrome', 'version': u'38.0.2125.111'},
> > {'name': u'com.google.Chrome', 'version': u'38.0.2125.104'},
> > {'name': u'com.google.Chrome', 'version': u'38.0.2125.101'},
> > {'name': u'com.google.Chrome', 'version': u'37.0.2062.94'},
> > {'name': u'com.google.Chrome', 'version': u'37.0.2062.120'},
> > {'name': u'com.google.Chrome', 'version': u'36.0.1985.143'},
> > {'name': u'com.google.Chrome', 'version': u'36.0.1985.125'},
> > {'name': u'com.google.Chrome', 'version': u'35.0.1916.153'},
> > {'name': u'com.google.Chrome', 'version': u'35.0.1916.114'},
> > {'name': u'com.google.Chrome', 'version': u'34.0.1847.137'},
> > {'name': u'com.google.Chrome', 'version': u'34.0.1847.131'},
> > {'name': u'com.google.Chrome', 'version': u'34.0.1847.116'},
> > {'name': u'com.google.Chrome', 'version': u'33.0.1750.152'},
> > {'name': u'com.google.Chrome', 'version': u'33.0.1750.149'},
> > {'name': u'com.google.Chrome', 'version': u'33.0.1750.146'},
> > {'name': u'com.google.Chrome', 'version': u'32.0.1700.107'},
> > {'name': u'com.google.Chrome', 'version': u'31.0.1650.63'},
> > {'name': u'com.google.Chrome', 'version': u'31.0.1650.57'}]
> >
> > sortedlist = sorted(mylist , key=lambda x, y: x['name'] LooseVersion(elem['version'])), reverse=True)
> 
> You'll need to fix LooseVersion or elem or both -- or show them so we 
> can help.
> 
> Emile
> 
> 
> 
> >
> > Thanks,
> > Charlie
> >

[toc] | [prev] | [next] | [standalone]


#86771

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-03-02 11:55 -0700
Message-ID<mailman.58.1425322577.13471.python-list@python.org>
In reply to#86768
On Mon, Mar 2, 2015 at 11:38 AM, Charles Heizer <ceh329@gmail.com> wrote:
> Sorry,
>
> sortedlist = sorted(mylist , key=lambda elem: "%s %s" % (elem['name'], LooseVersion(elem['version'])), reverse=True)
>
> This is what I was trying but LooseVersion() was not sorting version numbers like I thought it would. You will notice that Chrome version "40.0.2214.111" is higher than "40.0.2214.91" but in the end result it's not sorting it that way.

Because it's a string they're sorted lexicographically, and in that
ordering "40.0.2214.111" is less than "40.0.2214.91". Instead of a
string you should probably use some sort of version info tuple. A
simple tuple of ints may suffice, although you may need to get a
little cleverer if there are ever any version strings that aren't
entirely dotted numeric.

[toc] | [prev] | [next] | [standalone]


#86772

FromCharles Heizer <ceh329@gmail.com>
Date2015-03-02 10:58 -0800
Message-ID<8ccd65d8-3f1f-41ac-9092-9b0832d2fc49@googlegroups.com>
In reply to#86768
Never mind, the light bulb finally went off. :-\

sortedlist = sorted(mylist , key=lambda elem: "%s %s" % ( elem['name'], (".".join([i.zfill(5) for i in elem['version'].split(".")])) ), reverse=True)

On Monday, March 2, 2015 at 10:40:30 AM UTC-8, Charles Heizer wrote:
> Sorry,
> 
> sortedlist = sorted(mylist , key=lambda elem: "%s %s" % (elem['name'], LooseVersion(elem['version'])), reverse=True)
> 
> This is what I was trying but LooseVersion() was not sorting version numbers like I thought it would. You will notice that Chrome version "40.0.2214.111" is higher than "40.0.2214.91" but in the end result it's not sorting it that way.
> 
> Thanks,
> Charlie
> 
> On Monday, March 2, 2015 at 10:32:40 AM UTC-8, Emile van Sebille wrote:
> > On 3/2/2015 10:17 AM, Charles Heizer wrote:
> > > Hello,
> > > I'm new to python and I'm trying to find the right way to solve this issue I have.
> > >
> > > I'm trying to sort this list by name and then by version numbers. The problem I'm having is that I can not get the version numbers sorted with the highest at the top or sorted properly.
> > >
> > > mylist = [{'name': u'com.google.earth', 'version': u'7.1.2.2041'},
> > > {'name': u'com.google.earth', 'version': u'7.1.2.2019'},
> > > {'name': u'com.google.Chrome', 'version': u'40.0.2214.93'},
> > > {'name': u'com.google.Chrome', 'version': u'40.0.2214.91'},
> > > {'name': u'com.google.Chrome', 'version': u'40.0.2214.111'},
> > > {'name': u'com.google.Chrome', 'version': u'39.0.2171.99'},
> > > {'name': u'com.google.Chrome', 'version': u'39.0.2171.95'},
> > > {'name': u'com.google.Chrome', 'version': u'39.0.2171.71'},
> > > {'name': u'com.google.Chrome', 'version': u'38.0.2125.122'},
> > > {'name': u'com.google.Chrome', 'version': u'38.0.2125.111'},
> > > {'name': u'com.google.Chrome', 'version': u'38.0.2125.104'},
> > > {'name': u'com.google.Chrome', 'version': u'38.0.2125.101'},
> > > {'name': u'com.google.Chrome', 'version': u'37.0.2062.94'},
> > > {'name': u'com.google.Chrome', 'version': u'37.0.2062.120'},
> > > {'name': u'com.google.Chrome', 'version': u'36.0.1985.143'},
> > > {'name': u'com.google.Chrome', 'version': u'36.0.1985.125'},
> > > {'name': u'com.google.Chrome', 'version': u'35.0.1916.153'},
> > > {'name': u'com.google.Chrome', 'version': u'35.0.1916.114'},
> > > {'name': u'com.google.Chrome', 'version': u'34.0.1847.137'},
> > > {'name': u'com.google.Chrome', 'version': u'34.0.1847.131'},
> > > {'name': u'com.google.Chrome', 'version': u'34.0.1847.116'},
> > > {'name': u'com.google.Chrome', 'version': u'33.0.1750.152'},
> > > {'name': u'com.google.Chrome', 'version': u'33.0.1750.149'},
> > > {'name': u'com.google.Chrome', 'version': u'33.0.1750.146'},
> > > {'name': u'com.google.Chrome', 'version': u'32.0.1700.107'},
> > > {'name': u'com.google.Chrome', 'version': u'31.0.1650.63'},
> > > {'name': u'com.google.Chrome', 'version': u'31.0.1650.57'}]
> > >
> > > sortedlist = sorted(mylist , key=lambda x, y: x['name'] LooseVersion(elem['version'])), reverse=True)
> > 
> > You'll need to fix LooseVersion or elem or both -- or show them so we 
> > can help.
> > 
> > Emile
> > 
> > 
> > 
> > >
> > > Thanks,
> > > Charlie
> > >

[toc] | [prev] | [next] | [standalone]


#86778

FromPeter Otten <__peter__@web.de>
Date2015-03-02 20:23 +0100
Message-ID<mailman.61.1425324201.13471.python-list@python.org>
In reply to#86772
Charles Heizer wrote:

> Never mind, the light bulb finally went off. :-\
> 
> sortedlist = sorted(mylist , key=lambda elem: "%s %s" % ( elem['name'],
> (".".join([i.zfill(5) for i in elem['version'].split(".")])) ),
> reverse=True)

This lightbulb will break with version numbers > 99999 ;)

Here are two alternatives:

result = sorted(
    mylist,
    key=lambda elem: (elem['name'], LooseVersion(elem['version'])),
    reverse=True)

result = sorted(
    mylist,
    key=lambda e: (e["name"], tuple(map(int, e["version"].split(".")))),
    reverse=True)


Personally, I prefer to not use a lambda:

def name_version(elem):
    return elem['name'], LooseVersion(elem['version'])
    
result = sorted(mylist, key=name_version, reverse=True)

[toc] | [prev] | [next] | [standalone]


#86851

FromCharles Heizer <ceh329@gmail.com>
Date2015-03-03 07:56 -0800
Message-ID<432a0d61-a8ba-46ca-bc53-318e234fe168@googlegroups.com>
In reply to#86778
On Monday, March 2, 2015 at 11:23:37 AM UTC-8, Peter Otten wrote:
> Charles Heizer wrote:
> 
> > Never mind, the light bulb finally went off. :-\
> > 
> > sortedlist = sorted(mylist , key=lambda elem: "%s %s" % ( elem['name'],
> > (".".join([i.zfill(5) for i in elem['version'].split(".")])) ),
> > reverse=True)
> 
> This lightbulb will break with version numbers > 99999 ;)
> 
> Here are two alternatives:
> 
> result = sorted(
>     mylist,
>     key=lambda elem: (elem['name'], LooseVersion(elem['version'])),
>     reverse=True)
> 
> result = sorted(
>     mylist,
>     key=lambda e: (e["name"], tuple(map(int, e["version"].split(".")))),
>     reverse=True)
> 
> 
> Personally, I prefer to not use a lambda:
> 
> def name_version(elem):
>     return elem['name'], LooseVersion(elem['version'])
>     
> result = sorted(mylist, key=name_version, reverse=True)

Peter, thank you. Me being new to Python why don't you prefer to use a lambda?

[toc] | [prev] | [next] | [standalone]


#86853

FromChris Angelico <rosuav@gmail.com>
Date2015-03-04 03:09 +1100
Message-ID<mailman.22.1425398950.21433.python-list@python.org>
In reply to#86851
On Wed, Mar 4, 2015 at 2:56 AM, Charles Heizer <ceh329@gmail.com> wrote:
>> Personally, I prefer to not use a lambda:
>>
>> def name_version(elem):
>>     return elem['name'], LooseVersion(elem['version'])
>>
>> result = sorted(mylist, key=name_version, reverse=True)
>
> Peter, thank you. Me being new to Python why don't you prefer to use a lambda?

Using lambda is fine if it's really clear what's going on (usually, if
it's an extremely simple function), but if your expression goes across
multiple lines because of the function parameter, it's usually simpler
to break the function out into a separate def statement and then use
that. There's ultimately no difference[1] between a lambda function
and a def function, apart from the fact that a function created with
lambda always has the name "<lambda>".

ChrisA

[1] Modulo bugs, eg a weird edge case with lambda and yield; certainly
no intentional difference.

[toc] | [prev] | [next] | [standalone]


#86854

FromPaul Moore <p.f.moore@gmail.com>
Date2015-03-03 08:48 -0800
Message-ID<18d22144-9fce-40a5-9be5-eeec43194394@googlegroups.com>
In reply to#86853
On Tuesday, 3 March 2015 16:09:31 UTC, Chris Angelico  wrote:
> On Wed, Mar 4, 2015 at 2:56 AM, Charles Heizer wrote:
> >> Personally, I prefer to not use a lambda:
> >>
> >> def name_version(elem):
> >>     return elem['name'], LooseVersion(elem['version'])
> >>
> >> result = sorted(mylist, key=name_version, reverse=True)
> >
> > Peter, thank you. Me being new to Python why don't you prefer to use a lambda?
> 
> Using lambda is fine if it's really clear what's going on (usually, if
> it's an extremely simple function), but if your expression goes across
> multiple lines because of the function parameter, it's usually simpler
> to break the function out into a separate def statement and then use
> that. There's ultimately no difference[1] between a lambda function
> and a def function, apart from the fact that a function created with
> lambda always has the name "<lambda>".
> 
> ChrisA
> 
> [1] Modulo bugs, eg a weird edge case with lambda and yield; certainly
> no intentional difference.

The main point is that a def gives your function a name, whereas lambda is unnamed. It sometimes feels harder to have to think of a name for something that seems simple, like your key function. But when you come back to it in a few months, the name is incredibly useful documentation as to what's going on.

Paul

[toc] | [prev] | [next] | [standalone]


#86855

FromPeter Otten <__peter__@web.de>
Date2015-03-03 18:44 +0100
Message-ID<mailman.23.1425404702.21433.python-list@python.org>
In reply to#86851
Charles Heizer wrote:

> On Monday, March 2, 2015 at 11:23:37 AM UTC-8, Peter Otten wrote:
>> Charles Heizer wrote:
>> 
>> > Never mind, the light bulb finally went off. :-\
>> > 
>> > sortedlist = sorted(mylist , key=lambda elem: "%s %s" % ( elem['name'],
>> > (".".join([i.zfill(5) for i in elem['version'].split(".")])) ),
>> > reverse=True)
>> 
>> This lightbulb will break with version numbers > 99999 ;)
>> 
>> Here are two alternatives:
>> 
>> result = sorted(
>>     mylist,
>>     key=lambda elem: (elem['name'], LooseVersion(elem['version'])),
>>     reverse=True)
>> 
>> result = sorted(
>>     mylist,
>>     key=lambda e: (e["name"], tuple(map(int, e["version"].split(".")))),
>>     reverse=True)
>> 
>> 
>> Personally, I prefer to not use a lambda:
>> 
>> def name_version(elem):
>>     return elem['name'], LooseVersion(elem['version'])
>>     
>> result = sorted(mylist, key=name_version, reverse=True)
> 
> Peter, thank you. Me being new to Python why don't you prefer to use a
> lambda?

I find

def name_version(elem):
    return elem['name'], LooseVersion(elem['version'])

more readable than

lambda elem: (elem['name'], LooseVersion(elem['version']))

and I can understand what

>> result = sorted(mylist, key=name_version, reverse=True)

is supposed to do without grokking the implementation of name_version() 
first. I can spot a potential bug -- are the names really supposed to occur 
in reverse order, not just the versions? -- again without a look at the 
implementation.

If I intend to use the script more than once or if I want to rely on the 
result I can write unit tests for name_version() to increase confidence that 
it does what I expect.

Finally I can add a docstring to make it more discoverable in the 
interactive interpreter.

[toc] | [prev] | [next] | [standalone]


#86773

FromDave Angel <davea@davea.name>
Date2015-03-02 13:59 -0500
Message-ID<mailman.59.1425322796.13471.python-list@python.org>
In reply to#86768
On 03/02/2015 01:38 PM, Charles Heizer wrote:
> Sorry,
>
> sortedlist = sorted(mylist , key=lambda elem: "%s %s" % (elem['name'], LooseVersion(elem['version'])), reverse=True)
>
> This is what I was trying but LooseVersion() was not sorting version numbers like I thought it would. You will notice that Chrome version "40.0.2214.111" is higher than "40.0.2214.91" but in the end result it's not sorting it that way.
>

Please don't top-post.  put your remarks after whatever quoting you do.

You still haven't posted your LooseVersion() function source.  I agree 
with Emile that it's likely to be the problem.


-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#86813

FromJason Friedman <jsf80238@gmail.com>
Date2015-03-02 22:33 -0700
Message-ID<mailman.2.1425360823.21433.python-list@python.org>
In reply to#86768
>> This is what I was trying but LooseVersion() was not sorting version numbers like I thought it would. You will notice that Chrome version "40.0.2214.111" is higher than "40.0.2214.91" but in the end result it's not sorting it that way.
>
> Because it's a string they're sorted lexicographically, and in that
> ordering "40.0.2214.111" is less than "40.0.2214.91". Instead of a
> string you should probably use some sort of version info tuple. A
> simple tuple of ints may suffice, although you may need to get a
> little cleverer if there are ever any version strings that aren't
> entirely dotted numeric.

Also, Python 3.4 comes with an ipaddress module.

>>> import ipaddress
>>> address_string_1 = "2.2.3.4"
>>> address_string_2 = "10.2.3.4"
>>> address_string_2 > address_string_1
False
>>> ip_address_1 = ipaddress.ip_address(address_string_1)
>>> ip_address_2 = ipaddress.ip_address(address_string_2)
>>> ip_address_2 > ip_address_1
True

[toc] | [prev] | [next] | [standalone]


#86822

FromChris Angelico <rosuav@gmail.com>
Date2015-03-03 18:07 +1100
Message-ID<mailman.4.1425366433.21433.python-list@python.org>
In reply to#86768
On Tue, Mar 3, 2015 at 4:33 PM, Jason Friedman <jsf80238@gmail.com> wrote:
>>> This is what I was trying but LooseVersion() was not sorting version numbers like I thought it would. You will notice that Chrome version "40.0.2214.111" is higher than "40.0.2214.91" but in the end result it's not sorting it that way.
>>
>> Because it's a string they're sorted lexicographically, and in that
>> ordering "40.0.2214.111" is less than "40.0.2214.91". Instead of a
>> string you should probably use some sort of version info tuple. A
>> simple tuple of ints may suffice, although you may need to get a
>> little cleverer if there are ever any version strings that aren't
>> entirely dotted numeric.
>
> Also, Python 3.4 comes with an ipaddress module.

Heh, I think that miiiiiiiight be a bit abusive :) I'm not sure that
you want to depend on the version numbers fitting inside the rules for
IP addresses, especially given that the example has a component of
"2214".

The right way to compare version numbers is usually to split them on
dots, then treat each part as a separate number. I say "usually"
because there are complications like "alpha", "RC", "-git", "+deb7u1",
and so on, but if the entire version number consists of digits and
dots, then tuple(int(x) for x in version_number.split(".")) will give
you a properly-sortable key.

BTW, Jason: It's usually courteous to acknowledge who you're quoting.
If you look at the top of my post here, you'll see that there's a line
saying your name and email address, and the date/time that you made
your post; but underneath that is just straight text, because your
post didn't extend the same courtesy to the previous posters. When you
trim quoted text, do please try to keep at least the first
acknowledgement line - the one showing who you're actually quoting.
Whether or not you keep additional headers is up to you (sometimes
it's easy, but other times it's fiddly), but the first one is your
responsibility. Thanks!

ChrisA

[toc] | [prev] | [next] | [standalone]


#86846

FromJason Friedman <jsf80238@gmail.com>
Date2015-03-03 07:45 -0700
Message-ID<mailman.18.1425393922.21433.python-list@python.org>
In reply to#86768
On Tue, Mar 3, 2015 at 12:07 AM, Chris Angelico <rosuav@gmail.com> wrote:

> Heh, I think that miiiiiiiight be a bit abusive :) I'm not sure that
> you want to depend on the version numbers fitting inside the rules for
> IP addresses, especially given that the example has a component of
> "2214".
>

Indeed, I was mistaken

>>> ipaddress.ip_address("1000.1.2.3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/python/lib/python3.4/ipaddress.py", line 54, in ip_address
    address)
ValueError: '1000.1.2.3' does not appear to be an IPv4 or IPv6 address

I was overcome by how neat I think the ipaddress module is.
I have not used it yet, but I expect someday I will, and I appreciate
how Python makes my job easier by doing much of my work for me.  A
colleague yesterday asked how I guaranteed my temporary file names
would not collide with another file, and my answer was I don't have to
worry about it, someone else figured it out with the tempfile module.

[toc] | [prev] | [next] | [standalone]


#86847

FromChris Angelico <rosuav@gmail.com>
Date2015-03-04 01:50 +1100
Message-ID<mailman.19.1425394252.21433.python-list@python.org>
In reply to#86768
On Wed, Mar 4, 2015 at 1:45 AM, Jason Friedman <jsf80238@gmail.com> wrote:
> I appreciate
> how Python makes my job easier by doing much of my work for me.  A
> colleague yesterday asked how I guaranteed my temporary file names
> would not collide with another file, and my answer was I don't have to
> worry about it, someone else figured it out with the tempfile module.

Though in that case, Python isn't actually the one doing most of the
work - the tempfile module handballs responsibility to the lower-level
functions. But yes, there's HEAPS that you don't have to worry about,
because it's Someone Else's Problem.

ChrisA

[toc] | [prev] | [next] | [standalone]


#86829

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-03-03 18:55 +1100
Message-ID<54f568de$0$2877$c3e8da3$76491128@news.astraweb.com>
In reply to#86766
Charles Heizer wrote:

> Hello,
> I'm new to python and I'm trying to find the right way to solve this issue
> I have.
> 
> I'm trying to sort this list by name and then by version numbers. The
> problem I'm having is that I can not get the version numbers sorted with
> the highest at the top or sorted properly.
> 
> mylist = [{'name': u'com.google.earth', 'version': u'7.1.2.2041'},
> {'name': u'com.google.earth', 'version': u'7.1.2.2019'},
> {'name': u'com.google.Chrome', 'version': u'40.0.2214.93'},
> {'name': u'com.google.Chrome', 'version': u'40.0.2214.91'},
[...]
> ]
> 
> sortedlist = sorted(mylist , key=lambda x, y: x['name']
> LooseVersion(elem['version'])), reverse=True)

There's a syntax error there. Is there supposed to be a comma between the 
x['name'] and the LooseVersion function call?

Once you've fixed the syntax error, you can then fix the mysterious elem, 
and the fact that your key function takes too many arguments.

The key function should take *one* argument, which in your case is a dict. 
So:

def sort_by_version(d):
    name = d['name']
    version = d['version']
    return (name, [int(substr) for substr in version.split('.')])


sortedlist = sorted(mylist, key=sort_by_version)


should get you started. It may not quiet do what you want, but you can 
adjust the sort_by_version function as needed.



-- 
Steve

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web