On Mar 19, 8:57 pm, RichardOnRails <RichardDummyMailbox58...@USComputerGurus.com> wrote:
On Mar 19, 5:18 pm, Rob Biedenharn <R...@AgileConsultingLLC.com> > wrote:
> On Mar 19, 2009, at 4:42 PM, RichardOnRails wrote:
> > On Mar 18, 12:31 pm, Rob Biedenharn <R...@AgileConsultingLLC.com> > > > wrote:
> >> On Mar 18, 2009, at 1:58 AM, Christopher Dicely wrote:
> >>> Enumerable#sort lets you do this fairly easily with just a pure
> >>> array
> >>> of arrays, e.g., to sort the array-of-arrays "arr" by the first
> >>> column
> >>> ascending and the second descending:
> >>> arr.sort {|a,b| [a[0]<=>b[0], b[1]<=>a[1]].find {|x| x!=0} || 0}
> >> Not to detract to much from the other responses, but this ought to
> >> be:
> >> arr.sort {|a,b| (a[0] <=> b[0]).nonzero? || b[1] <=> a[1] }
> >> Take a look at what Numeric#nonzero? does. The docs specifically
> >> mention its use when chaining comparisons this way.
> >> Doing arr.sort_by {|a| [a[0], -a[1]] } only works if the second
> >> element responds to @- (like any Numeric would, but certainly not
> >> String).
> >> -Rob
> >>> On 3/17/09, RichardOnRails > > >>> <RichardDummyMailbox58...@uscomputergurus.com > > >>>> wrote:
> >>>> Hi,
> >>>> I've got an array of rows (and thus a matrix) created user
> >>>> FasterCSV
> >>>> to extract data from a CSV file. I'd like to sort the matrix on
> >>>> column A ascending and, within that, column B descending. I looked
> >>>> at
> >>>> Matrix, but it doesn't seem to address that functionality. Is
> >>>> there
> >>>> a package that does, or do I have to write my own SuperMatrix
> >>>> inherited from Matrix?
> >>>> Thanks in Advance,
> >>>> Richard
> >> Rob Biedenharn http://agileconsultingllc.com
> >> R...@AgileConsultingLLC.com
> > On Mar 18, 12:31 pm, Rob Biedenharn <R...@AgileConsultingLLC.com> > > > wrote:
> >> On Mar 18, 2009, at 1:58 AM, Christopher Dicely wrote:
> >>> Enumerable#sort lets you do this fairly easily with just a pure
> >>> array
> >>> of arrays, e.g., to sort the array-of-arrays "arr" by the first
> >>> column
> >>> ascending and the second descending:
> >>> arr.sort {|a,b| [a[0]<=>b[0], b[1]<=>a[1]].find {|x| x!=0} || 0}
> >> Not to detract to much from the other responses, but this ought to
> >> be:
> >> arr.sort {|a,b| (a[0] <=> b[0]).nonzero? || b[1] <=> a[1] }
> >> Take a look at what Numeric#nonzero? does. The docs specifically
> >> mention its use when chaining comparisons this way.
> >> Doing arr.sort_by {|a| [a[0], -a[1]] } only works if the second
> >> element responds to @- (like any Numeric would, but certainly not
> >> String).
> >> -Rob
> >>> On 3/17/09, RichardOnRails > > >>> <RichardDummyMailbox58...@uscomputergurus.com > > >>>> wrote:
> >>>> Hi,
> >>>> I've got an array of rows (and thus a matrix) created user
> >>>> FasterCSV
> >>>> to extract data from a CSV file. I'd like to sort the matrix on
> >>>> column A ascending and, within that, column B descending. I looked
> >>>> at
> >>>> Matrix, but it doesn't seem to address that functionality. Is
> >>>> there
> >>>> a package that does, or do I have to write my own SuperMatrix
> >>>> inherited from Matrix?
> >>>> Thanks in Advance,
> >>>> Richard
> >> Rob Biedenharn http://agileconsultingllc.com
> >> R...@AgileConsultingLLC.com
> > Hi Rob,
> > Thanks for your response. I don't want to be an expert on sorting
> > matrices. I just want to get my project working. (Don't we all 
> > Here's the essence of what I've got working, confirmed with debugging
> > puts'.
> > matrix =
> > FasterCSV.foreach(selectedCsvFile, :headers => false) do |row|
> > matrix << row
> > end
> > I want (in Excel terms) the matrix sorted on column B asc. and within
> > that col. I asc. Both columns are textual. Based on your guidance, I
> > added the line:
> > sortedMatrix = matrix.sort {|a,b| [a[1]<=>b[1], a[8] <=> b[8]]}
> > Ruby gave me a syntax error:
> > ProcessExports.rb:130:in `sort': undefined method `>' for [-1,
> > 1]:Array (NoMethodError)
> > I'm hoping the problem is that I'm invoking Array::Sort rather than
> > Enumerable::Sort but nothing my deteriorating brain could devise
> > worked. Any ideas.
> > Best wishes,
> > Richard
> Well, my guidance was:
> arr.sort {|a,b| (a[0] <=> b[0]).nonzero? || b[1] <=> a[1] }
> Which translates to your:
> sortedMatrix = matrix.sort {|a,b| (a[1]<=>b[1]).nonzero? || a[8]
> <=> b[8] }
> You might also need:
> matrix << row.to_a
> or
> matrix << row.fields
> in your loop, but a FasterCSV::Row probably behaves sufficiently like
> an Array to sort properly. Whether it continues to behave later (when
> you *really* need an Array), may resolve the question of whether you
> need to call #to_a or #fields on your row.
> Real code will always get you a better answer that pseudo-code.
> If you meant for either sort on Col.B or Col.I to be *descending*,
> then swap the a and b in the appropriate expression. (Your original
> question had the secondary sort descending, but the latest [with
> code ;-)] says "col. I asc.")
> -Rob
> Rob Biedenharn http://agileconsultingllc.com
> R...@AgileConsultingLLC.com
Rob,
Thank you very much for hanging in there with me until the fog lifted.
I thought about your advice and managed to mangle it. If I hadn't
been such a "wise guy", I could have translated your original advice
as you did and been on my way.
Regarding the asc/desc on the I col., I changed my mind midway and
decided my app requires asc. on I.
But I have a final question: I thought your expression had a flaw
because, in my view, "(a[1]<=>b[1]).nonzero?", if true, should cause
the block to return true rather than plus or minus.
So I concocted:
sortedMatrix = matrix.sort {|a,b| (v = a[1]<=>b[1]).nonzero? ? v : (a
[8] <=> b[8] )}
which works.
But yours works, too. So my understanding of how block evaluation
works when invoked by a calling function is flawed.
Do you have a simple explanation of the flaw in my thinking, or can
you point me to a relevant online tutorial on this? But don't trouble
yourself on this; it's only icing on the cake.
Thank you very much for the pains you took to get me going again.
Very best wishes,
Richard