tricky sort for happy visitors of Paris

Discussion in 'Ruby' started by Josselin, Dec 20, 2006.

  1. Josselin

    Josselin Guest

    all happy visitors of Paris know about the 'arrondissement', an
    administrative division of the city... 20 divisions

    selecting them from a city table I can map them as :

    ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris 2' ,
    'Paris 20' , 'Paris 3' , .... 'Paris 9' ]

    is there any way to sort this array and get :

    ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    'Paris 11' , ..... 'Paris 19' , 'Paris 20' ]

    which seems betetr in a list... ;-))

    thanks for your light

    joss
    Josselin, Dec 20, 2006
    #1
    1. Advertising

  2. Josselin

    Guest

    Hi --

    On Thu, 21 Dec 2006, Josselin wrote:

    > all happy visitors of Paris know about the 'arrondissement', an
    > administrative division of the city... 20 divisions
    >
    > selecting them from a city table I can map them as :
    >
    > ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris 2' ,
    > 'Paris 20' , 'Paris 3' , .... 'Paris 9' ]
    >
    > is there any way to sort this array and get :
    >
    > ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' , 'Paris
    > 11' , ..... 'Paris 19' , 'Paris 20' ]
    >
    > which seems betetr in a list... ;-))


    You could do:

    arronds.sort_by {|a| a[/\d+/].to_i }

    That will grab the digits, convert them to an integer, and sort based
    on that.


    David

    --
    Q. What's a good holiday present for the serious Rails developer?
    A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    aka The Ruby book for Rails developers!
    Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
    A. Ruby Power and Light, LLC (http://www.rubypal.com)
    , Dec 20, 2006
    #2
    1. Advertising

  3. On Dec 20, 2006, at 10:05 AM, Josselin wrote:

    > all happy visitors of Paris know about the 'arrondissement', an
    > administrative division of the city... 20 divisions
    >
    > selecting them from a city table I can map them as :
    >
    > ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris
    > 2' , 'Paris 20' , 'Paris 3' , .... 'Paris 9' ]
    >> paris = (1..20).map {|i| "Paris #{i}"}.sort

    => ["Paris 1", "Paris 10", "Paris 11", "Paris 12", "Paris 13", "Paris
    14", "Paris 15", "Paris 16", "Paris 17", "Paris 18", "Paris 19",
    "Paris 2", "Paris 20", "Paris 3", "Paris 4", "Paris 5", "Paris 6",
    "Paris 7", "Paris 8", "Paris 9"]

    > is there any way to sort this array and get :
    >
    > ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    > 'Paris 11' , ..... 'Paris 19' , 'Paris 20' ]
    >
    > which seems betetr in a list... ;-))
    >
    > thanks for your light
    >
    > joss


    >> paris.sort_by { |division| division.match(/(\d+)/)[1].to_i }

    => ["Paris 1", "Paris 2", "Paris 3", "Paris 4", "Paris 5", "Paris 6",
    "Paris 7", "Paris 8", "Paris 9", "Paris 10", "Paris 11", "Paris 12",
    "Paris 13", "Paris 14", "Paris 15", "Paris 16", "Paris 17", "Paris
    18", "Paris 19", "Paris 20"]

    if you have other cities or more than one embedded number, this is
    likely too simple, but it works for your example.

    -Rob

    Rob Biedenharn http://agileconsultingllc.com
    Rob Biedenharn, Dec 20, 2006
    #3
  4. On 12/20/06, Josselin <> wrote:
    > all happy visitors of Paris know about the 'arrondissement', an
    > administrative division of the city... 20 divisions
    >
    > selecting them from a city table I can map them as :
    >
    > ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris 2' ,
    > 'Paris 20' , 'Paris 3' , .... 'Paris 9' ]
    >
    > is there any way to sort this array and get :
    >
    > ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    > 'Paris 11' , ..... 'Paris 19' , 'Paris 20' ]
    >


    Somethings like (I've not tested the code):

    ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    'Paris 11' , ..... 'Paris 19' , 'Paris 20' ].sort do |a, b|
    re =3D /\s(\d+)$/
    re.match(a)
    ai =3D $1.to_i
    re.match(b)
    bi =3D $1.to_i
    ai <=3D> bi
    end

    Cheers

    --=20
    Nicolas Despr=E8s
    Nicolas Desprès, Dec 20, 2006
    #4
  5. On 20/12/06, Josselin <> wrote:
    > all happy visitors of Paris know about the 'arrondissement', an
    > administrative division of the city... 20 divisions
    >
    > selecting them from a city table I can map them as :
    >
    > ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris 2' ,
    > 'Paris 20' , 'Paris 3' , .... 'Paris 9' ]
    >
    > is there any way to sort this array and get :
    >
    > ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    > 'Paris 11' , ..... 'Paris 19' , 'Paris 20' ]
    >
    > which seems betetr in a list... ;-))
    >
    > thanks for your light
    >
    > joss
    >
    >
    >


    ["Paris 1","Paris 10","Paris 2"].sort_by{|a| a.split[1].to_i}

    Farrel
    Farrel Lifson, Dec 20, 2006
    #5
  6. Josselin

    Jamey Cribbs Guest

    Josselin wrote:
    > all happy visitors of Paris know about the 'arrondissement', an
    > administrative division of the city... 20 divisions
    >
    > selecting them from a city table I can map them as :
    >
    > ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris 2'
    > , 'Paris 20' , 'Paris 3' , .... 'Paris 9' ]
    >
    > is there any way to sort this array and get :
    >
    > ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    > 'Paris 11' , ..... 'Paris 19' , 'Paris 20' ]


    arrondissement_arr.sort_by { |a| a.split.last.to_i }


    Jamey

    Confidentiality Notice: This email message, including any attachments, is for the sole use of the intended recipient(s) and may contain confidential and/or privileged information. If you are not the intended recipient(s), you are hereby notified that any dissemination, unauthorized review, use, disclosure or distribution of this email and any materials contained in any attachments is prohibited. If you receive this message in error, or are not the intended recipient(s), please immediately notify the sender by email and destroy all copies of the original message, including attachments.
    Jamey Cribbs, Dec 20, 2006
    #6
  7. Josselin

    Uma Geller Guest

    > which seems betetr in a list... ;-))


    arrondissements = ["Paris 1", "Paris 2","Paris 4", "Paris 3"]
    sorted_array = arrondissements.sort_by {|e| e.split(" ")[1].to_i }

    ---
    Uma Geller
    http://umageller.wordpress.com
    Uma Geller, Dec 20, 2006
    #7
  8. This is just begging for a natural sort order method for the array
    class. Has anyone created one yet?
    Peter Hickman, Dec 20, 2006
    #8
  9. Josselin

    Uma Geller Guest

    > arrondissement_arr.sort_by { |a| a.split.last.to_i }

    your arys are better than myne ! :)

    thanks for the tip


    ---
    Uma Geller
    http://umageller.wordpress.com
    Uma Geller, Dec 20, 2006
    #9
  10. Josselin

    Guest

    On 12/20/06, Josselin <> wrote:
    [...]
    >
    > ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris 2' ,
    > 'Paris 20' , 'Paris 3' , .... 'Paris 9' ]
    >
    > is there any way to sort this array and get :
    >
    > ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    > 'Paris 11' , ..... 'Paris 19' , 'Paris 20' ]
    >
    > which seems betetr in a list... ;-))
    >


    I have had a similar problem several times (but not with Paris :), and
    I wrote a general utility function like this:

    def sort_numbers_numerically(arr)
    arr.sort_by do |str|
    i = 0
    str.split(/(\d+)/).map do |part|
    i += 1
    i % 2 == 0 ? part.to_i : part
    end
    end
    end

    It is of course very similar to the previously proposed solutions, but
    is more general in that it sorts strings with several numbers in them,
    treating each number "numerically" (one extreme example could be
    IP-numbers).

    /johan
    , Dec 20, 2006
    #10
  11. Josselin

    Josselin Guest

    On 2006-12-20 16:03:28 +0100, Josselin <> said:

    > all happy visitors of Paris know about the 'arrondissement', an
    > administrative division of the city... 20 divisions
    >
    > selecting them from a city table I can map them as :
    >
    > ['Paris 1' , 'Paris 10' , 'Paris 11' , ..... 'Paris 19' , 'Paris 2' ,
    > 'Paris 20' , 'Paris 3' , .... 'Paris 9' ]
    >
    > is there any way to sort this array and get :
    >
    > ['Paris 1' , 'Paris 2' , 'Paris 3' , .... 'Paris 9' , 'Paris 10' ,
    > 'Paris 11' , ..... 'Paris 19' , 'Paris 20' ]
    >
    > which seems betetr in a list... ;-))
    >
    > thanks for your light
    >
    > joss


    Thanks to all of you.... cannot invite you for a Xmas drink on the
    Champs-Elysees but cheers...
    (whatever I am not living in Paris.... but in the Celtic land.... the
    French Far West....
    Josselin, Dec 20, 2006
    #11
  12. wrote:
    > It is of course very similar to the previously proposed solutions, but
    > is more general in that it sorts strings with several numbers in them,
    > treating each number "numerically" (one extreme example could be
    > IP-numbers).

    What about this?
    arr.sort_by {|s| s.scan(/\d+/).map {|n| n.to_i } }

    Devin
    Devin Mullins, Dec 20, 2006
    #12
  13. Josselin

    Jos Backus Guest

    More generally:

    lizzy:~% irb
    irb(main):001:0> arrondissements = ["Paris 1", "Paris 2","Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    => ["Paris 1", "Paris 2", "Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    irb(main):002:0> sorted_array = arrondissements.sort_by {|e| [e.split(" ")]}
    => ["Lyon 1", "Lyon 2", "Paris 1", "Paris 2", "Paris 3", "Paris 4"]
    irb(main):003:0> % lizzy:~%

    --
    Jos Backus
    jos at catnook.com
    Jos Backus, Dec 20, 2006
    #13
  14. Jos Backus wrote:
    > More generally:
    >
    > lizzy:~% irb
    > irb(main):001:0> arrondissements = ["Paris 1", "Paris 2","Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    > => ["Paris 1", "Paris 2", "Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    > irb(main):002:0> sorted_array = arrondissements.sort_by {|e| [e.split(" ")]}
    > => ["Lyon 1", "Lyon 2", "Paris 1", "Paris 2", "Paris 3", "Paris 4"]
    > irb(main):003:0> % lizzy:~%
    >
    > --
    > Jos Backus
    > jos at catnook.com


    Won't work for

    arrondissements = "Paris 1", "Paris 2","Paris 12", "Paris 3",
    "Lyon 2", "Lyon 1"

    For the 2nd field, you need a numeric comparison.

    p arrondissements.sort_by {|e| e.split.inject{|a,b| [a,b.to_i] } }
    William James, Dec 20, 2006
    #14
  15. Josselin

    Guest

    Hi --

    On Thu, 21 Dec 2006, William James wrote:

    > Jos Backus wrote:
    >> More generally:
    >>
    >> lizzy:~% irb
    >> irb(main):001:0> arrondissements = ["Paris 1", "Paris 2","Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    >> => ["Paris 1", "Paris 2", "Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    >> irb(main):002:0> sorted_array = arrondissements.sort_by {|e| [e.split(" ")]}
    >> => ["Lyon 1", "Lyon 2", "Paris 1", "Paris 2", "Paris 3", "Paris 4"]
    >> irb(main):003:0> % lizzy:~%
    >>
    >> --
    >> Jos Backus
    >> jos at catnook.com

    >
    > Won't work for
    >
    > arrondissements = "Paris 1", "Paris 2","Paris 12", "Paris 3",
    > "Lyon 2", "Lyon 1"
    >
    > For the 2nd field, you need a numeric comparison.
    >
    > p arrondissements.sort_by {|e| e.split.inject{|a,b| [a,b.to_i] } }


    Or:

    require 'scanf'
    p @arrondissements.sort_by {|e| e.scanf("%s%d") }


    David

    --
    Q. What's a good holiday present for the serious Rails developer?
    A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    aka The Ruby book for Rails developers!
    Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
    A. Ruby Power and Light, LLC (http://www.rubypal.com)
    , Dec 21, 2006
    #15
  16. Josselin

    Jos Backus Guest

    On Thu, Dec 21, 2006 at 08:05:06AM +0900, William James wrote:
    > Jos Backus wrote:
    > > More generally:
    > >
    > > lizzy:~% irb
    > > irb(main):001:0> arrondissements = ["Paris 1", "Paris 2","Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    > > => ["Paris 1", "Paris 2", "Paris 4", "Paris 3", "Lyon 2", "Lyon 1"]
    > > irb(main):002:0> sorted_array = arrondissements.sort_by {|e| [e.split(" ")]}
    > > => ["Lyon 1", "Lyon 2", "Paris 1", "Paris 2", "Paris 3", "Paris 4"]
    > > irb(main):003:0> % lizzy:~%
    > >
    > > --
    > > Jos Backus
    > > jos at catnook.com

    >
    > Won't work for
    >
    > arrondissements = "Paris 1", "Paris 2","Paris 12", "Paris 3",
    > "Lyon 2", "Lyon 1"
    >
    > For the 2nd field, you need a numeric comparison.
    >
    > p arrondissements.sort_by {|e| e.split.inject{|a,b| [a,b.to_i] } }


    Oops, you're right, I missed that. Clever use of inject, by the way.

    --
    Jos Backus
    jos at catnook.com
    Jos Backus, Dec 21, 2006
    #16
  17. Josselin

    Père Noël Guest

    Josselin <> wrote:

    > whatever I am not living in Paris.... but in the Celtic land.... the
    > French Far West....


    Then, u're living with an unefficient(*) umbrella over the head ???

    * unefficient because in france "little britany" their is too much wing
    to let you open your umbrella ;-)
    --
    Père Noël
    Père Noël, Dec 21, 2006
    #17
  18. Josselin

    Guest

    On 12/20/06, Devin Mullins <> wrote:
    >
    > wrote:
    > > It is of course very similar to the previously proposed solutions, but
    > > is more general in that it sorts strings with several numbers in them,
    > > treating each number "numerically" (one extreme example could be
    > > IP-numbers).

    >
    > What about this?
    > arr.sort_by {|s| s.scan(/\d+/).map {|n| n.to_i } }
    >


    My example with IP-numbers was perhaps an ill-chosen one. I just
    wanted to indicate that my solution could handle several numbers in
    the string.

    It also considers the string parts as significant. Suppose the input
    is like this:

    arr = [
    "Paris 1", "Paris 5", "Paris 14",
    "Lyon 2", "Lyon 6", "Lyon 15",
    ]

    Your code will give:

    ["Paris 1", "Lyon 2", "Paris 5", "Lyon 6", "Paris 14", "Lyon 15"]

    and my code gives:

    ["Lyon 2", "Lyon 6", "Lyon 15", "Paris 1", "Paris 5", "Paris 14"]

    I guess the code one would choose depends on exactly what one wants to
    accomplish. In the general case it may be important to consider the
    string parts too (e.g. "Paris" and "Lyon") and not just look at the
    numbers.

    /johan
    , Dec 21, 2006
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. francois lepoutre

    Paris python user group?

    francois lepoutre, Apr 21, 2004, in forum: Python
    Replies:
    11
    Views:
    564
  2. meltedown
    Replies:
    9
    Views:
    1,008
    Steve Pugh
    Oct 17, 2006
  3. Replies:
    9
    Views:
    522
    CBFalconer
    Apr 25, 2006
  4. Navin
    Replies:
    1
    Views:
    672
    Ken Schaefer
    Sep 9, 2003
  5. Daniel Martin
    Replies:
    1
    Views:
    158
    Daniel Martin
    Sep 6, 2006
Loading...

Share This Page