Re: Sort on linkedlists with double values (inside main list)

2024-05-21 Thread M.v.Gulik
On Tue, 21 May 2024 at 14:01, Paul King  wrote:

> On Tue, May 21, 2024 at 3:13 PM M.v.Gulik  wrote:
> >
> > After fixing my local bug I rechecked the "*.sort{ a, b -> a.y == b.y ?
> -a.y <=> -b.y : a.x <=> b.x }" variant.
> > Same result/conclusion.
>
> In terms of referencing the properties, you'd want to swap the order
> you have above, i.e. you'd not want to have y ? y : x but rather y ? x
> : y or x ? y : x.
>

Darn. Yea, your right. I messed it up (again) :-/ .
After fixing that (and triple checking) it worked like advertised.
Thanks again.

On Tue, 21 May 2024 at 14:01, Paul King  wrote:

> Also, the "*.sort" would only be needed if you have lists of lists of maps.
>

Ditching that ".sort{ a, b -> a.x <=> b.x }.sort{ a, b -> -a.y <=>
-b.y}" idea of mine.
(might play around with it a bit more on a rainy day to see in which cases
it would fail, just out of curiosity.)


Re: Sort on linkedlists with double values (inside main list)

2024-05-21 Thread Paul King
On Tue, May 21, 2024 at 3:13 PM M.v.Gulik  wrote:
>
> After fixing my local bug I rechecked the "*.sort{ a, b -> a.y == b.y ? -a.y 
> <=> -b.y : a.x <=> b.x }" variant.
> Same result/conclusion.

In terms of referencing the properties, you'd want to swap the order
you have above, i.e. you'd not want to have y ? y : x but rather y ? x
: y or x ? y : x.
Also, the "*.sort" would only be needed if you have lists of lists of maps.

> However, on a hunch, I split in into two separate consecutive sorts. "*.sort{ 
> a, b -> a.x <=> b.x }.sort{ a, b -> -a.y <=> -b.y }"
> So far this seems to do the job of fully sorting my 2d/coordinates set. (so 
> far: no guaranties, as the used data set is somewhat limited and specific.)

This doesn't seem right as written. Perhaps you are abbreviating and
leaving out some info that I am missing.


Re: Sort on linkedlists with double values (inside main list)

2024-05-21 Thread Paul King
Indeed OC, your version is shorter and easier to read (in my eyes too).

Whether it is more performant depends on whether the respective
compareTo method isn't too slow compared to the equals method.

On Tue, May 21, 2024 at 2:22 AM o...@ocs.cz  wrote:
>
> Paul,
>
> side question, completely irrelevant to the original problem, just occurred 
> to me when I read this...
>
> On 20. 5. 2024, at 17:02, Paul King  wrote:
> println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{ a, b -> a.x == b.x 
> ? a.y <=> b.y : a.x <=> b.x }) // works
>
>
> Wouldn't sort { a,b -> a.x<=>b.x ?: a.y<=>b.y } be both more efficient and 
> better readable and intention-revealing? Or do I overlook some reason why it 
> would be a bad idea?
>
> Thanks,
> OC
>
>
> On Tue, May 21, 2024 at 12:52 AM Paul King  wrote:
>
>
> If you have only two dimensions, you'll get away with your solution
> for small integer coordinate values. Here is a counter example with
> integers:
>
> println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{[it.x,
> it.y]}) // broken
> println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{ a, b ->
> a.x == b.x ? a.y <=> b.y : a.x <=> b.x }) // works
>
> On Tue, May 21, 2024 at 12:25 AM M.v.Gulik  wrote:
>
>
>
> On Mon, 20 May 2024 at 15:40, Paul King  wrote:
>
>
> What sort result are you trying to achieve? There should be no need to
> perform any recursion.
>
>
>
> Main target was reordering some set of randomly ordered x,y coordinates into 
> (for example*) a x,y(left to right, top to bottom) order (*:where any of the 
> actual sort directions could be easily flipped).
>
> So far "*.sort{[it.y, it.x]}" seems the best and easiest way to do this 
> (despite its Float/Double caveat).
>
>


Re: Sort on linkedlists with double values (inside main list)

2024-05-21 Thread OCsite
In general, this is not a safe approach, unless you are sure that the sorting 
algorithm is stable (never reordering items regarded „same“).

I regret to say I do not know whether Groovy sort is documented to be always 
stable or not.

All the best,
OC


> On 21. 5. 2024, at 7:12, M.v.Gulik  wrote:
> 
> After fixing my local bug I rechecked the "*.sort{ a, b -> a.y == b.y ? -a.y 
> <=> -b.y : a.x <=> b.x }" variant.
> Same result/conclusion.
> 
> However, on a hunch, I split in into two separate consecutive sorts. "*.sort{ 
> a, b -> a.x <=> b.x }.sort{ a, b -> -a.y <=> -b.y }"
> So far this seems to do the job of fully sorting my 2d/coordinates set. (so 
> far: no guaranties, as the used data set is somewhat limited and specific.)



Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread M.v.Gulik
After fixing my local bug I rechecked the "*.sort{ a, b -> a.y == b.y ?
-a.y <=> -b.y : a.x <=> b.x }" variant.
Same result/conclusion.

However, on a hunch, I split in into two separate consecutive sorts.
"*.sort{ a, b -> a.x <=> b.x }.sort{ a, b -> -a.y <=> -b.y }"
So far this seems to do the job of fully sorting my 2d/coordinates set. (so
far: no guaranties, as the used data set is somewhat limited and specific.)


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread M.v.Gulik
On Mon, 20 May 2024 at 17:02, Paul King  wrote:

> This might even be more obvious:
>
> println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{[it.x,
> it.y]}) // broken: [[x:2, y:1], [x:1, y:100], [x:2, y:500]]
> println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{ a, b -> a.x
> == b.x ? a.y <=> b.y : a.x <=> b.x }) // works
>

 Aha. Thanks.
Definitely needed to see it 'not' working in one of the other value types.
+(*spotte a bug in my source code that gave me the wrong result on my
"*.sort{ a, b ->...}" test. ... it picked the wrong sort-case*. :-/ )


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread MG

Hi Paul,

1. I don't use Python and what you guys are saying is of course
   technically correct for Groovy, but I must admit I have run into the
   same mistake in the past, intuitively assuming that a list would be
   component-wise-comparable to another list in Groovy
1. (At least if teh lists have the same size, but one could
   potentially make the larger list win (i.e. +1 compare result) in
   case all existing elements are equal...)
2. We currently use our own comparable n-tuple class class that gives
   the expected behavior of comparing the 1st, 2nd, 3rd, etc tuple
   member until the result is != zero.
3. It might imho make sense to support this in Groovy directly, e.g.:
1. collectionOfFourVectors.sortByList { [ it.x0, it.x1, it.x2,
   it.x3 ] }
4. It would be even nicer if the standard sort method could be used
   like this, or even make collections component-wise-comparable in
   general, but that would evidently be a much bigger change with some
   breaking change potential.
1. (Although it might not be as bad as it looks, since the current
   behavior is pretty useseless in practice (?))

Cheers,
mg


On 20/05/2024 17:02, Paul King wrote:

This might even be more obvious:

println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{[it.x,
it.y]}) // broken: [[x:2, y:1], [x:1, y:100], [x:2, y:500]]
println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{ a, b -> a.x
== b.x ? a.y <=> b.y : a.x <=> b.x }) // works

On Tue, May 21, 2024 at 12:52 AM Paul King  wrote:

If you have only two dimensions, you'll get away with your solution
for small integer coordinate values. Here is a counter example with
integers:

println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{[it.x,
it.y]}) // broken
println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{ a, b ->
a.x == b.x ? a.y <=> b.y : a.x <=> b.x }) // works

On Tue, May 21, 2024 at 12:25 AM M.v.Gulik  wrote:


On Mon, 20 May 2024 at 15:40, Paul King  wrote:

What sort result are you trying to achieve? There should be no need to
perform any recursion.


Main target was reordering some set of randomly ordered x,y coordinates into 
(for example*) a x,y(left to right, top to bottom) order (*:where any of the 
actual sort directions could be easily flipped).

So far "*.sort{[it.y, it.x]}" seems the best and easiest way to do this 
(despite its Float/Double caveat).


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread o...@ocs.cz
Paul,

side question, completely irrelevant to the original problem, just occurred to 
me when I read this...

> On 20. 5. 2024, at 17:02, Paul King  wrote:
> println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{ a, b -> a.x == b.x 
> ? a.y <=> b.y : a.x <=> b.x }) // works

Wouldn't sort { a,b -> a.x<=>b.x ?: a.y<=>b.y } be both more efficient and 
better readable and intention-revealing? Or do I overlook some reason why it 
would be a bad idea?

Thanks,
OC

> 
> On Tue, May 21, 2024 at 12:52 AM Paul King  wrote:
>> 
>> If you have only two dimensions, you'll get away with your solution
>> for small integer coordinate values. Here is a counter example with
>> integers:
>> 
>> println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{[it.x,
>> it.y]}) // broken
>> println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{ a, b ->
>> a.x == b.x ? a.y <=> b.y : a.x <=> b.x }) // works
>> 
>> On Tue, May 21, 2024 at 12:25 AM M.v.Gulik  wrote:
>>> 
>>> 
>>> On Mon, 20 May 2024 at 15:40, Paul King  wrote:
 
 What sort result are you trying to achieve? There should be no need to
 perform any recursion.
>>> 
>>> 
>>> Main target was reordering some set of randomly ordered x,y coordinates 
>>> into (for example*) a x,y(left to right, top to bottom) order (*:where any 
>>> of the actual sort directions could be easily flipped).
>>> 
>>> So far "*.sort{[it.y, it.x]}" seems the best and easiest way to do this 
>>> (despite its Float/Double caveat).



Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread Paul King
This might even be more obvious:

println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{[it.x,
it.y]}) // broken: [[x:2, y:1], [x:1, y:100], [x:2, y:500]]
println ([[x:1, y:100],  [x:2, y:1], [x: 2, y:500]].sort{ a, b -> a.x
== b.x ? a.y <=> b.y : a.x <=> b.x }) // works

On Tue, May 21, 2024 at 12:52 AM Paul King  wrote:
>
> If you have only two dimensions, you'll get away with your solution
> for small integer coordinate values. Here is a counter example with
> integers:
>
> println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{[it.x,
> it.y]}) // broken
> println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{ a, b ->
> a.x == b.x ? a.y <=> b.y : a.x <=> b.x }) // works
>
> On Tue, May 21, 2024 at 12:25 AM M.v.Gulik  wrote:
> >
> >
> > On Mon, 20 May 2024 at 15:40, Paul King  wrote:
> >>
> >> What sort result are you trying to achieve? There should be no need to
> >> perform any recursion.
> >
> >
> > Main target was reordering some set of randomly ordered x,y coordinates 
> > into (for example*) a x,y(left to right, top to bottom) order (*:where any 
> > of the actual sort directions could be easily flipped).
> >
> > So far "*.sort{[it.y, it.x]}" seems the best and easiest way to do this 
> > (despite its Float/Double caveat).


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread Paul King
If you have only two dimensions, you'll get away with your solution
for small integer coordinate values. Here is a counter example with
integers:

println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{[it.x,
it.y]}) // broken
println ([[x:  1, y: 69273666],  [x: 69273666, y: 1]].sort{ a, b ->
a.x == b.x ? a.y <=> b.y : a.x <=> b.x }) // works

On Tue, May 21, 2024 at 12:25 AM M.v.Gulik  wrote:
>
>
> On Mon, 20 May 2024 at 15:40, Paul King  wrote:
>>
>> What sort result are you trying to achieve? There should be no need to
>> perform any recursion.
>
>
> Main target was reordering some set of randomly ordered x,y coordinates into 
> (for example*) a x,y(left to right, top to bottom) order (*:where any of the 
> actual sort directions could be easily flipped).
>
> So far "*.sort{[it.y, it.x]}" seems the best and easiest way to do this 
> (despite its Float/Double caveat).


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread Søren Berg Glasius
But when you sort on the value that is an ArrayList ([it.y, it.x]) you rely
on the *hashCode()* of that ArrayList not the values inside.
So it is a coincidence that it works for others than Float/Double. The
right syntax in Groovy is as described by Paul King.

Den man. 20. maj 2024 kl. 15.25 skrev M.v.Gulik :

>
> On Mon, 20 May 2024 at 15:40, Paul King  wrote:
>
>> What sort result are you trying to achieve? There should be no need to
>> perform any recursion.
>>
>
> Main target was reordering some set of randomly ordered x,y coordinates
> into (*for example**) a *x,y*(*left to right, top to bottom*) order (**:where
> any of the actual sort directions could be easily flipped*).
>
> So far "**.sort{[it.y, it.x]}*" seems the best and easiest way to do this
> (*despite its Float/Double caveat*).
>


-- 

Med venlig hilsen,
Søren Berg Glasius

Hedevej 1, Gl. Rye, 8680 Ry
Mobile: +45 40 44 91 88
--- Press ESC once to quit - twice to save the changes.


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread M.v.Gulik
On Mon, 20 May 2024 at 15:40, Paul King  wrote:

> What sort result are you trying to achieve? There should be no need to
> perform any recursion.
>

Main target was reordering some set of randomly ordered x,y coordinates
into (*for example**) a *x,y*(*left to right, top to bottom*) order (**:where
any of the actual sort directions could be easily flipped*).

So far "**.sort{[it.y, it.x]}*" seems the best and easiest way to do
this (*despite
its Float/Double caveat*).


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread Paul King
What sort result are you trying to achieve? There should be no need to
perform any recursion.

On Mon, May 20, 2024 at 11:36 PM M.v.Gulik  wrote:
>
> Tried "*.sort{ a, b -> a.x == b.x ? a.y <=> b.y : a.x <=> b.x }" in the 
> actual source code so see its effect
> And it turns out its not doing the same job as "*.sort{[it.y, it.x]}" (not 
> unless, I guess, its run recursively until the list-order stopped changing 
> ... which I'm ofc not going to do)
>


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread Paul King
The one argument closure variant of sort is expecting the closure to
return a comparable. The values of any two items are sorted according
to that comparable.

ArrayLists aren't comparable. In that case the hashCode is used as a
fallback for the comparison value. The hashCode for a Java array list
is calculated in terms of the hashCodes of the individual elements and
will only work by fluke, e.g. for small values of integers.

If the floats are small, you could use something like:
sorttest.sort{ it.x * 1000 + it.y }
sorttest.sort{ it.x * -1000 - it.y }

Cheers, Paul.

On Mon, May 20, 2024 at 8:53 PM M.v.Gulik  wrote:
>
> Verified that "*.sort{ a, b -> a.x == b.x ? -a.y <=> -b.y : -a.x <=> -b.x }" 
> actually behaves ok when using Double or Float values (ie: same ordered 
> output as with Integer or BigDecimal values).
>
> Why "*.sort{[ -it.x, -it.y]}" behaved differently when using Double or Float 
> values in this case is beyond me ... Guess i just chalk it up as some 
> peculiar groovy thing.


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread M.v.Gulik
Tried "**.sort{ a, b -> a.x == b.x ? a.y <=> b.y : a.x <=> b.x }*" in the
actual source code so see its effect
And it turns out its not doing the same job as "**.sort{[it.y, it.x]}*" (*not
unless, I guess, its run recursively until the list-order stopped changing
... which I'm ofc not going to do*)


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread M.v.Gulik
Verified that "**.sort{ a, b -> a.x == b.x ? -a.y <=> **-**b.y : **-**a.x
<=> **-**b.x }*" actually behaves ok when using Double or Float values (ie:
same ordered output as with Integer or BigDecimal values).

Why "**.sort{[ -it.x, -it.y]}*" behaved differently when using Double or
Float values in this case is beyond me ... Guess i just chalk it up as some
peculiar groovy thing.

>


Re: Sort on linkedlists with double values (inside main list)

2024-05-20 Thread M.v.Gulik
I'm after information so I might better understand why "**.sort{[ -it.x,
-it.y]}*" (*vs "*.sort{[ it.x, it.y]}"*) has no effect on Double and Float
values in this particular case (*both sorts return identical ordered list*.
Not so when using Integer or BigDecimal values).

Mainly working with Python (*but I have no choice to use Groovy in this
case, which is kinda alien to me*). As such I prefer "**.sort{[it.x, it.y]}*"
over "**.sort{ a, b -> a.x == b.x ? a.y <=> b.y : a.x <=> b.x }*" ... + The
latter might, for all I know at this moment, exhibit the same behavior when
it comes to Double or Float values.


Re: Sort on linkedlists with double values (inside main list)

2024-05-19 Thread Paul King
I am not 100% sure what you are after. If you are wanting sort by x
and then y, you just want something like this:

sorttest.sort{ a, b -> a.x == b.x ? a.y <=> b.y : a.x <=> b.x }
sorttest.sort{ a, b -> a.x == b.x ? b.y <=> a.y : b.x <=> a.x } //
reverse of above

On Mon, May 20, 2024 at 6:43 AM M.v.Gulik  wrote:
>
> Hmm. Same deal with Float values.
>
> (Guess I'm down to enforce BigDecimal values in case of sorting with
> Float or Double values.)


Re: Sort on linkedlists with double values (inside main list)

2024-05-19 Thread M.v.Gulik
Hmm. Same deal with Float values.

(Guess I'm down to enforce BigDecimal values in case of sorting with
Float or Double values.)


Sort on linkedlists with double values (inside main list)

2024-05-19 Thread M.v.Gulik
I'm totally bewildered by the following. (And googling it did not help).

Erm ... markup ... don't know.

[code]
def sorttest = []
if(1){
sorttest = [[x:3,y:2],[x:4,y:1],[x:2,y:3],[x:1,y:4]]
// if(DBL){println('sorttest|1a: ' + sorttest)}
assert sorttest instanceof List
assert sorttest.size() == 4
assert sorttest[0] instanceof java.util.LinkedHashMap
assert sorttest[0].size() == 2
assert sorttest[0].x instanceof Integer

sorttest.sort{[it.x, it.y]}
// if(DBL){println('sorttest|1a: ' + sorttest)}
sorttest.sort{[-it.x, -it.y]}
// if(DBL){println('sorttest|1b: ' + sorttest)}

sorttest.sort{[it.y, it.x]}
// if(DBL){println('sorttest|2a: ' + sorttest)}
sorttest.sort{[-it.y, -it.x]}
// if(DBL){println('sorttest|2b: ' + sorttest)}
}
if(1){
sorttest = [[x:3,y:2],[x:4,y:1],[x:2,y:3],[x:1,y:4]]
// if(DBL){println('sorttest|0a: ' + sorttest)}
for (int i in 1..sorttest.size()){
i -= 1
sorttest[i] = [x:sorttest[i].x.toDouble(),
y:sorttest[i].y.toDouble()]
}
// if(DBL){println('sorttest|0b: ' + sorttest)}
assert sorttest instanceof List
assert sorttest.size() == 4
assert sorttest[0] instanceof java.util.LinkedHashMap
assert sorttest[0].size() == 2
assert sorttest[0].x instanceof Double

sorttest.sort{[it.x, it.y]}
// if(DBL){println('sorttest|1a: ' + sorttest)}
sorttest.sort{[-it.x, -it.y]} // reversing the output (well trying)
// if(DBL){println('sorttest|1b: ' + sorttest)}

sorttest.sort{[it.y, it.x]}
// if(DBL){println('sorttest|2a: ' + sorttest)}
sorttest.sort{[-it.y, -it.x]} // reversing the output (well trying)
// if(DBL){println('sorttest|2b: ' + sorttest)}
}

[/code]
[Output]:
sorttest|0: [[x:3, y:2], [x:4, y:1], [x:2, y:3], [x:1, y:4]]
sorttest|1a: [[x:1, y:4], [x:2, y:3], [x:3, y:2], [x:4, y:1]]
sorttest|1b: [[x:4, y:1], [x:3, y:2], [x:2, y:3], [x:1, y:4]]
sorttest|2a: [[x:4, y:1], [x:3, y:2], [x:2, y:3], [x:1, y:4]]
sorttest|2b: [[x:1, y:4], [x:2, y:3], [x:3, y:2], [x:4, y:1]]

sorttest|0a: [[x:3, y:2], [x:4, y:1], [x:2, y:3], [x:1, y:4]]
sorttest|0b: [[x:3.0, y:2.0], [x:4.0, y:1.0], [x:2.0, y:3.0],
[x:1.0, y:4.0]]
sorttest|1a: [[x:1.0, y:4.0], [x:2.0, y:3.0], [x:3.0, y:2.0],
[x:4.0, y:1.0]]
sorttest|1b: [[x:1.0, y:4.0], [x:2.0, y:3.0], [x:3.0, y:2.0],
[x:4.0, y:1.0]] -- No Change ???
sorttest|2a: [[x:4.0, y:1.0], [x:3.0, y:2.0], [x:2.0, y:3.0],
[x:1.0, y:4.0]]
sorttest|2b: [[x:4.0, y:1.0], [x:3.0, y:2.0], [x:2.0, y:3.0],
[x:1.0, y:4.0]] -- No Change ???
[/Output]

If this it something version specific (like: groovy-3.0.12) ... I
can't change that (not in this case).