|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Dear all,
I have many arrays like a=[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13}, {'a',10,'b',7},{'a',5,'b',3}] which I'd like to sort such that I get the hashes with the highest values of 'a' first. If there are ties, I'd like to sort them (but not the entire array) such that the highest values of 'b' come first. So I can't just sort for 'a'-values first and then for 'b'-values, as this would destroy the first sort order. Is there a built-in way of getting the ties in sorting, such as an Array of the results of the <=> comparisons ? Thank you! Best regards, Axel -- Psssst! Schon vom neuen GMX MultiMessenger gehört? Der kanns mit allen: http://www.gmx.net/de/go/multimessenger |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Alle venerd=EC 14 settembre 2007, Axel Etzold ha scritto:
> Dear all, > > I have many arrays like > > a=3D[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13}, > {'a',10,'b',7},{'a',5,'b',3}] > > which I'd like to sort such that I get the hashes with the highest > values of 'a' first. If there are ties, I'd like to sort them (but not > the entire array) such > that the highest values of 'b' come first. > So I can't just sort for 'a'-values first and then for 'b'-values, > as this would destroy the first sort order. > > Is there a built-in way of getting the ties in sorting, such as an > Array of the results of the <=3D> comparisons ? > > Thank you! > > Best regards, > > Axel This should work: a.sort_by{|i| [i['a'], i['b']]}.reverse a.sort_by returns the hashes sorted by the values of 'a' and, in case of a= =20 tie, the values of 'b', both in ascending order. Applying reverse to this=20 array gives you the correct order. The result is the following: [{"a"=3D>13, "b"=3D>13}, {"a"=3D>10, "b"=3D>7}, {"a"=3D>10, "b"=3D>4}, {"a"= =3D>10, "b"=3D>3},=20 {"a"=3D>5, "b"=3D>13}, {"a"=3D>5, "b"=3D>3}] I hope this s Stefano |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Axel Etzold wrote:
> Dear all, > > I have many arrays like > > a=[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13}, > {'a',10,'b',7},{'a',5,'b',3}] > > which I'd like to sort such that I get the hashes with the highest > values of 'a' first. If there are ties, I'd like to sort them (but not > the entire array) such > that the highest values of 'b' come first. > So I can't just sort for 'a'-values first and then for 'b'-values, > as this would destroy the first sort order. > > Is there a built-in way of getting the ties in sorting, such as an > Array of the results of the <=> comparisons ? > > Thank you! > > Best regards, > > Axel Built in? I don't know about that, but it's pretty easy. I'm sure your real situation is more complex than the example you gave, but I really think this is the easiest way (and you can avoid making comparisons twice by caching the value of hash1['a'] <=> hash2['a'], if you wish): a=[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13}, {'a',10,'b',7},{'a',5,'b',3}] a.sort do |hash1, hash2| if hash1['a'] == hash2['a'] hash1['b'] <=> hash2['b'] else hash1['a'] <=> hash2['a'] end end The above is essentially a redefinition of <=> on hashes with elements "a" and "b". The only thing you need to be sure of is that ordering is strict--that you never have x < y < z but z < x. That should be no problem if you only try to break ties. Hope this s, Dan |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Sep 14, 2007, at 8:42 AM, Dan Zwell wrote:
> Axel Etzold wrote: >> Dear all, >> I have many arrays like >> a=[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13}, >> {'a',10,'b',7},{'a',5,'b',3}] >> which I'd like to sort such that I get the hashes with the highest >> values of 'a' first. If there are ties, I'd like to sort them (but >> not >> the entire array) such >> that the highest values of 'b' come first. >> So I can't just sort for 'a'-values first and then for 'b'-values, >> as this would destroy the first sort order. >> Is there a built-in way of getting the ties in sorting, such as an >> Array of the results of the <=> comparisons ? >> Thank you! >> Best regards, >> Axel > > Built in? I don't know about that, but it's pretty easy. I'm sure > your real situation is more complex than the example you gave, but > I really think this is the easiest way (and you can avoid making > comparisons twice by caching the value of hash1['a'] <=> hash2 > ['a'], if you wish): > > a=[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13}, > {'a',10,'b',7},{'a',5,'b',3}] > a.sort do |hash1, hash2| > if hash1['a'] == hash2['a'] > hash1['b'] <=> hash2['b'] > else > hash1['a'] <=> hash2['a'] > end > end > > The above is essentially a redefinition of <=> on hashes with > elements "a" and "b". The only thing you need to be sure of is that > ordering is strict--that you never have x < y < z but z < x. That > should be no problem if you only try to break ties. > > Hope this s, > Dan a.sort do |h1,h2| (h1['a'] <=> h2['a']).nonzero? || h1['b'] <=> h2['b'] end The Numeric#nonzero? is exactly for this kind of thing. If its receiver is 0 it returns nil so chaining with || will work. (And you don't have to compare the 'a' values twice.) -Rob Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Rob Biedenharn wrote:
> a.sort do |h1,h2| > (h1['a'] <=> h2['a']).nonzero? || h1['b'] <=> h2['b'] > end > > The Numeric#nonzero? is exactly for this kind of thing. If its receiver > is 0 it returns nil so chaining with || will work. (And you don't have > to compare the 'a' values twice.) > > -Rob > Neat, I didn't know about that. Dan |
|
![]() |
| Outils de la discussion | |
|
|