Sort pseudo-lists

Say I've got a string like this:

"{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}"

- imagine it's aspiring to be a list of sublists, with 4 reals in each list. I want to produce a sorted version:

(1.4 2.2 2.1 4.2)
(2.1 3.14 2.4 2.2)
(3.1 1.3 2.5 2.1)

What would be a good way to do this?

thanks

Pete

Well, if you can count on the data format, the following is pretty simple:

irb(main):001:0> arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}".tr("{}", "")
=> [[3.1, 1.3, 2.5, 2.1], [2.1, 3.1, 2.4, 2.2], [1.4, 2.2, 2.1, 4.2]]
irb(main):002:0>
irb(main):003:0* arr.sort { |a, b| a.first <=> b.first }
=> [[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]

Hope that helps.

James Edward Gray II

···

On Oct 10, 2005, at 4:46 PM, pete boardman wrote:

Say I've got a string like this:

"{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}"

- imagine it's aspiring to be a list of sublists, with 4 reals in each list. I want to produce a sorted version:

(1.4 2.2 2.1 4.2)
(2.1 3.14 2.4 2.2)
(3.1 1.3 2.5 2.1)

What would be a good way to do this?

harp:~ > cat a.rb
   buf = "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}"
   buf.gsub! %r/ { /x, ' [ '
   buf.gsub! %r/ } /x, ' ] '

   require 'yaml'
   list = YAML::load(buf).map{|s| s.sort}.sort

   p list

   harp:~ > ruby a.rb
   [[1.3, 2.1, 2.5, 3.1], [1.4, 2.1, 2.2, 4.2], [2.1, 2.2, 2.4, 3.1]]

-a

···

On Tue, 11 Oct 2005, pete boardman wrote:

Say I've got a string like this:

"{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}"

- imagine it's aspiring to be a list of sublists, with 4 reals in each list. I want to produce a sorted version:

(1.4 2.2 2.1 4.2)
(2.1 3.14 2.4 2.2)
(3.1 1.3 2.5 2.1)

What would be a good way to do this?

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

Thanks for these answers!

Pete

One more thing - I forgot that I need to get the result back to a string... So (thanks to your help andn Ruby's 'eval') I can go from this:

"{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}"

to this:

[[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]

but I can't persuade the 'p' method to turn this back into a string:

"[[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]"

(and I should be able to go from here to :

"{{1.4, 2.2, 2.1, 4.2}, {2.1, 3.1, 2.4, 2.2}, {3.1, 1.3, 2.5, 2.1}}"

on my own :slight_smile:

Pete

Thanks, James - simple, elegant, and nearly perfect! Is it easy to sort the array of arrays by their second, third, and fourth entries as well:

ie such that

[[2.1, 2.2, 9.5, 2.1], [2.1, 2.2, 2.4, 2.2], [2.1, 2.2, 2.1, 4.2]]

sorts to

[[2.1, 2.2, 2.1, 4.2],[2.1, 2.2, 2.4, 2.2],[2.1, 2.2, 9.5, 2.1]]

rather than

[[2.1, 2.2, 9.5, 2.1], [2.1, 2.2, 2.4, 2.2], [2.1, 2.2, 2.1, 4.2]]

thanks

Pete

···

On 10 Oct 2005, at 22:53, James Edward Gray II wrote:

arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}".tr("{}", "")
arr.sort { |a, b| a.first <=> b.first }

James Edward Gray II wrote:

irb(main):001:0> arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4,
2.2}, {1.4, 2.2, 2.1, 4.2}}".tr("{}", "")
=> [[3.1, 1.3, 2.5, 2.1], [2.1, 3.1, 2.4, 2.2], [1.4, 2.2, 2.1, 4.2]]
irb(main):002:0>
irb(main):003:0* arr.sort { |a, b| a.first <=> b.first }
=> [[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]

arr.sort_by{|x| x.first }

pete boardman wrote:

One more thing - I forgot that I need to get the result back to a string... So (thanks to your help andn Ruby's 'eval') I can go from this:

"{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}"

to this:

[[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]

but I can't persuade the 'p' method to turn this back into a string:

Kernel#p actually prints stuff, using #inspect rather than #to_s. So,
my_array.inspect will give you the below String.

"[[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]"

(and I should be able to go from here to :

"{{1.4, 2.2, 2.1, 4.2}, {2.1, 3.1, 2.4, 2.2}, {3.1, 1.3, 2.5, 2.1}}"

on my own :slight_smile:

Yep, just do the exact inverse of how you got the normal Array syntax.
Why do you need to translate it back to the same form, though?

Pete

E

James Edward Gray II wrote:

Well, if you can count on the data format, the following is pretty simple:

irb(main):001:0> arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2, 2.1, 4.2}}".tr("{}", "")

I'd just like to remind everyone that if the data is input by users, calling eval on it is a really bad idea...

mathew

···

--
<URL:http://www.pobox.com/~meta/&gt;
          WE HAVE TACOS

That's actually the default behaviour, so you can just say arr.sort

martin

···

pete boardman <pete.boardman@pobox.com> wrote:

On 10 Oct 2005, at 22:53, James Edward Gray II wrote:

> arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2,
> 2.1, 4.2}}".tr("{}", "")
> arr.sort { |a, b| a.first <=> b.first }

Thanks, James - simple, elegant, and nearly perfect! Is it easy to
sort the array of arrays by their second, third, and fourth entries
as well:

pete boardman wrote:

Is it easy to
sort the array of arrays by their second, third, and fourth entries
as well:

ie such that

[[2.1, 2.2, 9.5, 2.1], [2.1, 2.2, 2.4, 2.2], [2.1, 2.2, 2.1, 4.2]]

sorts to

[[2.1, 2.2, 2.1, 4.2],[2.1, 2.2, 2.4, 2.2],[2.1, 2.2, 9.5, 2.1]]

rather than

[[2.1, 2.2, 9.5, 2.1], [2.1, 2.2, 2.4, 2.2], [2.1, 2.2, 2.1, 4.2]]

thanks

Pete

a = "{{2.1, 2.2, 9.5, 2.1}, {2.1, 2.2, 2.4, 2.2}, {2.1, 2.2, 2.1,
4.2}}"\
  [2..-3].split( '}, {' ).map{|x| x.split( /,\s+/ ).map{|s| s.to_f } }
p a.sort

Hi --

···

On Tue, 11 Oct 2005, William James wrote:

James Edward Gray II wrote:

irb(main):001:0> arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4,
2.2}, {1.4, 2.2, 2.1, 4.2}}".tr("{}", "")
=> [[3.1, 1.3, 2.5, 2.1], [2.1, 3.1, 2.4, 2.2], [1.4, 2.2, 2.1, 4.2]]
irb(main):002:0>
irb(main):003:0* arr.sort { |a, b| a.first <=> b.first }
=> [[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]

arr.sort_by{|x| x.first }

Better yet:

   arr.sort

which will handle tie-breaks automatically.

David

--
David A. Black
dblack@wobblini.net

Kernel#p actually prints stuff, using #inspect rather than #to_s. So,
my_array.inspect will give you the below String.

Right, so I can get access to the form shown by 'p'. Great!

"[[1.4, 2.2, 2.1, 4.2], [2.1, 3.1, 2.4, 2.2], [3.1, 1.3, 2.5, 2.1]]"
(and I should be able to go from here to :
"{{1.4, 2.2, 2.1, 4.2}, {2.1, 3.1, 2.4, 2.2}, {3.1, 1.3, 2.5, 2.1}}"
on my own :slight_smile:

Yep, just do the exact inverse of how you got the normal Array syntax.
Why do you need to translate it back to the same form, though?

I was hoping that nobody was going to ask :-). Oh well: the curly bracket format is AppleScript's list notation, and information is often passed around in AppleScript using lists and lists of lists. However, AppleScript lists are not very powerful (and there are hardly any built-in methods). This trick of passing a string version of a list to Ruby and making use of Ruby's more powerful methods works nicely once I learned how to get the information back from Ruby to AppleScript in list form.

thanks again all

Pete

···

On 11 Oct 2005, at 20:51, ES wrote:

Martin DeMello wrote:

arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2,
2.1, 4.2}}".tr("{}", "")
arr.sort { |a, b| a.first <=> b.first }

Thanks, James - simple, elegant, and nearly perfect! Is it easy to
sort the array of arrays by their second, third, and fourth entries
as well:

That's actually the default behaviour, so you can just say arr.sort

Strictly speaking that's wrong: the code above and arr.sort are not
equivalent because arr.sort will evaluate all elements of embedded arrays
while the code above will only honor the first one:

a=[[1,2,3],[1,0,0]]

=> [[1, 2, 3], [1, 0, 0]]

a.sort

=> [[1, 0, 0], [1, 2, 3]]

a.sort_by {|x| x.first}

=> [[1, 2, 3], [1, 0, 0]]

a.sort {|x,y| x.first <=> y.first}

=> [[1, 2, 3], [1, 0, 0]]

Kind regards

    robert

···

pete boardman <pete.boardman@pobox.com> wrote:

On 10 Oct 2005, at 22:53, James Edward Gray II wrote:

Martin DeMello wrote:

arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4, 2.2,
2.1, 4.2}}".tr("{}", "")
arr.sort { |a, b| a.first <=> b.first }

Thanks, James - simple, elegant, and nearly perfect! Is it easy to
sort the array of arrays by their second, third, and fourth entries
as well:

That's actually the default behaviour, so you can just say arr.sort

Strictly speaking that's wrong: the code above and arr.sort are not
equivalent because arr.sort will evaluate all elements of embedded arrays
while the code above will only honor the first one:

I showed how to do just the first, then Pete said:

Is it easy to sort the array of arrays by their second, third, and fourth entries
as well

Making Martin's answer right on.

James Edward Gray II

···

On Oct 11, 2005, at 9:51 AM, Robert Klemme wrote:

pete boardman <pete.boardman@pobox.com> wrote:

On 10 Oct 2005, at 22:53, James Edward Gray II wrote:

James Edward Gray II wrote:

···

On Oct 11, 2005, at 9:51 AM, Robert Klemme wrote:

Martin DeMello wrote:

pete boardman <pete.boardman@pobox.com> wrote:

On 10 Oct 2005, at 22:53, James Edward Gray II wrote:

arr = eval "{{3.1, 1.3, 2.5, 2.1}, {2.1, 3.1, 2.4, 2.2}, {1.4,
2.2,
2.1, 4.2}}".tr("{}", "")
arr.sort { |a, b| a.first <=> b.first }

Thanks, James - simple, elegant, and nearly perfect! Is it easy to
sort the array of arrays by their second, third, and fourth entries
as well:

That's actually the default behaviour, so you can just say arr.sort

Strictly speaking that's wrong: the code above and arr.sort are not
equivalent because arr.sort will evaluate all elements of embedded
arrays
while the code above will only honor the first one:

I showed how to do just the first, then Pete said:

Is it easy to sort the array of arrays by their second, third,
and fourth entries
as well

Making Martin's answer right on.

Erm, yes. My fault! Apparently I'm not able to read news properly any
more - I should go home now.

Sorry for the noise

    robert