Evaluating this:
| a b c | a := OrderedCollection new. a add: (Point x: 1 y:1). a add: (Point x: 1 y:2). a add: (Point x: 1 y:3). a add: (Point x: 2 y:1). a add: (Point x: 2 y:2). a add: (Point x: 2 y:3). b := a asSortedCollection: [:p1 : p2 | (p1 y < p2 y) ]. results in this: a SortedCollection(2@1 1@1 1@2 2@2 1@3 2@3) But evaluating this: | a b c | a := OrderedCollection new. a add: (Point x: 1 y:1). a add: (Point x: 1 y:2). a add: (Point x: 1 y:3). a add: (Point x: 2 y:1). a add: (Point x: 2 y:2). a add: (Point x: 2 y:3). b := a asSortedCollection: [:p1 : p2 | (p1 x < p2 x) and: [p1 y < p2 y]]. results in this: a SortedCollection(2@1 1@3 1@1 2@2 1@2 2@3) I know I am overlooking something real simple, but why isn't this major minor sort working. Thanks. |
"Donald MacQueen" <[hidden email]> schrieb im Newsbeitrag
news:9fh9ah$94s$[hidden email]... > Evaluating this: > | a b c | > a := OrderedCollection new. > a add: (Point x: 1 y:1). > a add: (Point x: 1 y:2). > a add: (Point x: 1 y:3). > a add: (Point x: 2 y:1). > a add: (Point x: 2 y:2). > a add: (Point x: 2 y:3). > b := a asSortedCollection: [:p1 : p2 | (p1 y < p2 y) ]. > results in this: a SortedCollection(2@1 1@1 1@2 2@2 1@3 2@3) > > But evaluating this: > | a b c | > a := OrderedCollection new. > a add: (Point x: 1 y:1). > a add: (Point x: 1 y:2). > a add: (Point x: 1 y:3). > a add: (Point x: 2 y:1). > a add: (Point x: 2 y:2). > a add: (Point x: 2 y:3). > b := a asSortedCollection: [:p1 : p2 | (p1 x < p2 x) and: [p1 y < p2 y]]. > results in this: a SortedCollection(2@1 1@3 1@1 2@2 1@2 2@3) > > I know I am overlooking something real simple, but why isn't this major > minor sort working. Thanks. Don, if p1 x < p2 x is false, then the points are swapped, regardless of the y component. (Lazy evaluation). (see False>>and:) Ingo |
In reply to this post by jWarrior
> a := OrderedCollection new.
> a add: (Point x: 1 y:1). > a add: (Point x: 1 y:2). > a add: (Point x: 1 y:3). > a add: (Point x: 2 y:1). > a add: (Point x: 2 y:2). > a add: (Point x: 2 y:3). Don, in case you want a solution, here is one possible: b := a asSortedCollection:[:p1 :p2| p1 x < p2 x]. result := OrderedCollection new. idx := 1. bSize := b size. [idx <= bSize] whileTrue:[|tmp xGroup| tmp := SortedCollection new sortBlock:[:p1 :p2 | p1 y < p2 y];yourself. xGroup := (b at: idx) x. [idx <= bSize and:[(b at: idx) x = xGroup]] whileTrue:[ tmp add: (b at: idx). idx := idx + 1 ]. tmp do:[:e| result add: e]]. Bye Ingo |
In reply to this post by jWarrior
[hidden email] (Donald MacQueen) wrote (abridged):
> b := a asSortedCollection: [:p1 : p2 | > (p1 x < p2 x) and: [p1 y < p2 y]]. > results in this: a SortedCollection(2@1 1@3 1@1 2@2 1@2 2@3) > > I know I am overlooking something real simple, but why isn't this major > minor sort working. Thanks. Because the sort block doesn't give a total ordering. Which do you think is the smaller of 2@1 and 1@3? Try it: 2@1 < 1@3: p1 x < p2 x ==> 2 < 1 ==> false p1 y < p2 y ==> 1 < 3 ==> true false and: [true] ==> false so 2@1 < 1@3 is false Also: 1@3 < 2@1: p1 x < p2 x ==> 1 < 2 ==> true p1 y < p2 y ==> 3 < 1 ==> false true and: [false] ==> false so 1@3 < 2@1 is false Hence the sort has no way of knowing which Point to put first. You probably want something like: b := a asSortedCollection: [:p1 :p2| (p1 x < p2 x) or: [(p1 x = p2 x) and: [p1 y < p2 y]]]. This only compares the y coordinates if the x coordinates are equal. Another way to write it is: b := a asSortedCollection: [:p1 :p2| (p1 x ~= p2 x) ifTrue: [p1 x < p2 x] ifFalse: [p1 y < p2 y]]. which makes the symmetry a bit clearer. It's also easier to extend to more levels (especially if we use a method instead, and so can do an early return in the #ifTrue: branch). Dave Harris, Nottingham, UK | "Weave a circle round him thrice, [hidden email] | And close your eyes with holy dread, | For he on honey dew hath fed http://www.bhresearch.co.uk/ | And drunk the milk of Paradise." |
In reply to this post by Ingo Blank
"Ingo Blank" <[hidden email]> schrieb im Newsbeitrag
news:3b1c2fec$0$139$[hidden email]... > > "Donald MacQueen" <[hidden email]> schrieb im Newsbeitrag > news:9fh9ah$94s$[hidden email]... > > Evaluating this: > > | a b c | > > a := OrderedCollection new. > > a add: (Point x: 1 y:1). > > a add: (Point x: 1 y:2). > > a add: (Point x: 1 y:3). > > a add: (Point x: 2 y:1). > > a add: (Point x: 2 y:2). > > a add: (Point x: 2 y:3). > > b := a asSortedCollection: [:p1 : p2 | (p1 y < p2 y) ]. > > results in this: a SortedCollection(2@1 1@1 1@2 2@2 1@3 2@3) > > > > But evaluating this: > > | a b c | > > a := OrderedCollection new. > > a add: (Point x: 1 y:1). > > a add: (Point x: 1 y:2). > > a add: (Point x: 1 y:3). > > a add: (Point x: 2 y:1). > > a add: (Point x: 2 y:2). > > a add: (Point x: 2 y:3). > > b := a asSortedCollection: [:p1 : p2 | (p1 x < p2 x) and: [p1 y < p2 > > results in this: a SortedCollection(2@1 1@3 1@1 2@2 1@2 2@3) > > > > I know I am overlooking something real simple, but why isn't this major > > minor sort working. Thanks. > > Don, > > if p1 x < p2 x is false, then the points are swapped, regardless of the y > component. > (Lazy evaluation). (see False>>and:) > > Ingo > Forget that! Has nothing to do with lazy evaluation, but with "and" logic. (A parallel version, i.e. (p1 x < p2 x) asParameter + (p2 y < p2 y) asParamter == 2 gives the same result) If the first expression is false, then the pairs are swapped. When comparing them at a later time, then the first expression evaluates to true and the second is evaluated. If this is now false too, then they are swapped again, destroying the previous order. So you never get a two stage sort with "and" logic. Ingo |
In reply to this post by jWarrior
Donald
> Evaluating this: > | a b c | > a := OrderedCollection new. > a add: (Point x: 1 y:1). > a add: (Point x: 1 y:2). > a add: (Point x: 1 y:3). > a add: (Point x: 2 y:1). > a add: (Point x: 2 y:2). > a add: (Point x: 2 y:3). > b := a asSortedCollection: [:p1 : p2 | (p1 y < p2 y) ]. > results in this: a SortedCollection(2@1 1@1 1@2 2@2 1@3 2@3) [ snip ] I think you want the following: | a b | a := OrderedCollection new. a add: (Point x: 1 y:1). a add: (Point x: 1 y:2). a add: (Point x: 1 y:3). a add: (Point x: 2 y:1). a add: (Point x: 2 y:2). a add: (Point x: 2 y:3). b := a asSortedCollection: [:p1 : p2 | ( p1 x < p2 x ) ifTrue: [ true ] ifFalse: [ p1 x = p2 x and: [ p1 y < p2 y ] ] ]. Which yields: SortedCollection (1@1 1@2 1@3 2@1 2@2 2@3) Hope that helps! Regards, Randy |
Doh! (sound of head slap).
What -was- I thinking! Thanks to all who set me back on the path of truth and enlightenment. "Randy A. Ynchausti" <[hidden email]> wrote in message news:nI4T6.13$[hidden email]... > Donald > > > Evaluating this: > > | a b c | > > a := OrderedCollection new. > > a add: (Point x: 1 y:1). > > a add: (Point x: 1 y:2). > > a add: (Point x: 1 y:3). > > a add: (Point x: 2 y:1). > > a add: (Point x: 2 y:2). > > a add: (Point x: 2 y:3). > > b := a asSortedCollection: [:p1 : p2 | (p1 y < p2 y) ]. > > results in this: a SortedCollection(2@1 1@1 1@2 2@2 1@3 2@3) > > [ snip ] > > I think you want the following: > > | a b | > a := OrderedCollection new. > a add: (Point x: 1 y:1). > a add: (Point x: 1 y:2). > a add: (Point x: 1 y:3). > a add: (Point x: 2 y:1). > a add: (Point x: 2 y:2). > a add: (Point x: 2 y:3). > b := a asSortedCollection: [:p1 : p2 | > ( p1 x < p2 x ) > ifTrue: [ true ] > ifFalse: [ p1 x = p2 x and: [ p1 y < p2 y ] ] ]. > > Which yields: > > SortedCollection (1@1 1@2 1@3 2@1 2@2 2@3) > > > Hope that helps! > > Regards, > > Randy > > > |
Free forum by Nabble | Edit this page |