Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #19552 > unrolled thread

About keeping my array 1 based after having sorted it

Started by"Tony" <tony.johansson@inport.com>
First post2013-05-01 17:18 +0200
Last post2013-05-04 16:14 +0100
Articles 16 — 7 participants

Back to article view | Back to comp.lang.javascript


Contents

  About keeping my array 1 based after having sorted it "Tony" <tony.johansson@inport.com> - 2013-05-01 17:18 +0200
    Re: About keeping my array 1 based after having sorted it Daniel Pitts <newsgroup.nospam@virtualinfinity.net> - 2013-05-01 08:26 -0700
      Re: About keeping my array 1 based after having sorted it "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2013-05-01 19:43 +0200
        Re: About keeping my array 1 based after having sorted it Daniel Pitts <newsgroup.nospam@virtualinfinity.net> - 2013-05-01 15:15 -0700
          Re: About keeping my array 1 based after having sorted it "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2013-05-02 09:35 +0200
            Re: About keeping my array 1 based after having sorted it Denis McMahon <denismfmcmahon@gmail.com> - 2013-05-02 14:31 +0000
        Re: About keeping my array 1 based after having sorted it Denis McMahon <denismfmcmahon@gmail.com> - 2013-05-01 22:12 +0000
          Re: About keeping my array 1 based after having sorted it "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2013-05-02 09:36 +0200
    Re: About keeping my array 1 based after having sorted it Scott Sauyet <scott.sauyet@gmail.com> - 2013-05-02 08:52 -0700
      Re: About keeping my array 1 based after having sorted it Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-05-03 01:26 +0200
        Re: About keeping my array 1 based after having sorted it Scott Sauyet <scott.sauyet@gmail.com> - 2013-05-03 08:53 -0700
          Re: About keeping my array 1 based after having sorted it Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-05-03 18:39 +0200
            Re: About keeping my array 1 based after having sorted it Scott Sauyet <scott.sauyet@gmail.com> - 2013-05-03 11:00 -0700
              Sorting arrays of objects (was: About keeping my array 1 based after having sorted it) Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-05-05 01:00 +0200
                Re: Sorting arrays of objects (was: About keeping my array 1 based after having sorted it) Scott Sauyet <scott.sauyet@gmail.com> - 2013-05-05 08:53 -0700
          Re: About keeping my array 1 based after having sorted it Dr J R Stockton <reply1300@merlyn.demon.co.uk.invalid> - 2013-05-04 16:14 +0100

#19552 — About keeping my array 1 based after having sorted it

From"Tony" <tony.johansson@inport.com>
Date2013-05-01 17:18 +0200
SubjectAbout keeping my array 1 based after having sorted it
Message-ID<klrbhd$duk$1@dont-email.me>
I use a 1 based array because I need to find each record that is a multiple 
of three later in the code.
After I have used this sort below the array is then back to use zero based.

I can handle this in his way
for (var i = 0; i < bookingArray.length; i++)
          {
              a[++j] = bookingArray[i];
          }
          bookingArray = a;

but I just wonder if I can make the sort to keep my 1 based array ?

bookingArray.sort(function (a, b)
                   {
                       var aObjectid = a.Objectid;
                       var bObjectid = b.Objectid;

                       var aFromtime = new Date(a.Fromtime);
                       var bFromtime = new Date(b.Fromtime);

                       if (aObjectid == bObjectid)
                           return (aFromtime < bFromtime) ? -1 : (aFromtime 
 > bFromtime) ? 1 : 0;
                       else
                           return (aObjectid < bObjectid) ? -1 : 1;
                   });

//Tony 

[toc] | [next] | [standalone]


#19553

FromDaniel Pitts <newsgroup.nospam@virtualinfinity.net>
Date2013-05-01 08:26 -0700
Message-ID<guagt.23460$zH4.10295@newsfe13.iad>
In reply to#19552
On 5/1/13 8:18 AM, Tony wrote:
> I use a 1 based array because I need to find each record that is a
> multiple of three later in the code.
> After I have used this sort below the array is then back to use zero based.
>
> I can handle this in his way
> for (var i = 0; i < bookingArray.length; i++)
>           {
>               a[++j] = bookingArray[i];
>           }
>           bookingArray = a;
>
> but I just wonder if I can make the sort to keep my 1 based array ?
>
> bookingArray.sort(function (a, b)
>                    {
>                        var aObjectid = a.Objectid;
>                        var bObjectid = b.Objectid;
>
>                        var aFromtime = new Date(a.Fromtime);
>                        var bFromtime = new Date(b.Fromtime);
>
>                        if (aObjectid == bObjectid)
>                            return (aFromtime < bFromtime) ? -1 :
> (aFromtime > bFromtime) ? 1 : 0;
>                        else
>                            return (aObjectid < bObjectid) ? -1 : 1;
>                    });
>
> //Tony

If you put a dummy value at the front of the array that is always before 
any other value, that'll keep it where you want.

Alternatively, instead of using 1 base, use 0 base and when you need 
"every third element", for (var i = 2; i < bookingArray.length; i+=3)

[toc] | [prev] | [next] | [standalone]


#19555

From"Evertjan." <exxjxw.hannivoort@inter.nl.net>
Date2013-05-01 19:43 +0200
Message-ID<XnsA1B3C892E7F06eejj99@194.109.133.133>
In reply to#19553
Daniel Pitts wrote on 01 mei 2013 in comp.lang.javascript:

> Alternatively, instead of using 1 base, use 0 base and when you need 
> "every third element", for (var i = 2; i < bookingArray.length; i+=3)
> 

for (var i = 0; i < bookingArray.length/3; i++)
    x = bookingArray[i * 3 + 1];



-- 
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)

[toc] | [prev] | [next] | [standalone]


#19558

FromDaniel Pitts <newsgroup.nospam@virtualinfinity.net>
Date2013-05-01 15:15 -0700
Message-ID<Jtggt.32252$2b6.23400@newsfe10.iad>
In reply to#19555
On 5/1/13 10:43 AM, Evertjan. wrote:
> Daniel Pitts wrote on 01 mei 2013 in comp.lang.javascript:
>
>> Alternatively, instead of using 1 base, use 0 base and when you need
>> "every third element", for (var i = 2; i < bookingArray.length; i+=3)
>>
>
> for (var i = 0; i < bookingArray.length/3; i++)
>      x = bookingArray[i * 3 + 1];
works well enough for a one based array.  The multiply and add inside 
the loop make the C programmer in me cringe.

Anyway, your addition to this thread was completely irrelevant to the 
OPs question.

[toc] | [prev] | [next] | [standalone]


#19568

From"Evertjan." <exxjxw.hannivoort@inter.nl.net>
Date2013-05-02 09:35 +0200
Message-ID<XnsA1B4618E3BD9eejj99@194.109.133.133>
In reply to#19558
Daniel Pitts wrote on 02 mei 2013 in comp.lang.javascript:

> On 5/1/13 10:43 AM, Evertjan. wrote:
>> Daniel Pitts wrote on 01 mei 2013 in comp.lang.javascript:
>>
>>> Alternatively, instead of using 1 base, use 0 base and when you need
>>> "every third element", for (var i = 2; i < bookingArray.length; i+=3)
>>>
>>
>> for (var i = 0; i < bookingArray.length/3; i++)
>>      x = bookingArray[i * 3 + 1];

+ 2];

> works well enough for a one based array.  The multiply and add inside 
> the loop make the C programmer in me cringe.
> 
> Anyway, your addition to this thread was completely irrelevant to the 
> OPs question.

1/
This is not a helpdesk. Your irrelevancy is quite irrelevant.

2/
This is not about C.

There is no compiled code to be kept and kept short.
The loss of speed/cpu-time will only be apparent in heavy use,
not expected in clientside browser programming.
[In serverside Javascript, I would suggest using a database, not an array]

3/
It can be easily extended to:

for (var i = 0; i < bookingArray.length/3; i++) {
   x = bookingArray[i * 3 + 1];
   y = bookingArray[i * 3 + 2];
   z = bookingArray[i * 3 + 3];
   ... 
};

4/
The above 3/ shows the weakness in the OQ specification
of the need for a 1-based array:

for (var i = 0; i < bookingArray.length/3; i++) {
   x = bookingArray[i * 3 + 0];
   y = bookingArray[i * 3 + 1];
   z = bookingArray[i * 3 + 2];
   ... 
};

5/
or even the weakness of the supposed simplicity 
of an 1-dimensional array here:

var betterArray = [];
for (var i = 0; i < bookingArray.length/3; i++) {
   betterArray[i]  = [ 
        bookingArray[i * 3 + 0],
        bookingArray[i * 3 + 1],
        bookingArray[i * 3 + 2] 
   ];
};

var bookingNr = 37; // 1-based if still required
var lastName = 1; // constant
alert( 'lastName' = betterArray[bookingNr-1][lastName] );



-- 
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)

[toc] | [prev] | [next] | [standalone]


#19582

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2013-05-02 14:31 +0000
Message-ID<klttcq$m0v$2@dont-email.me>
In reply to#19568
On Thu, 02 May 2013 09:35:24 +0200, Evertjan. wrote:

> The above 3/ shows the weakness in the OQ specification of the need for
> a 1-based array:

Indeed, the OP might be better off using an array of objects, where each 
object contained 3 values, and he could:

function booking( a, b ) {
  this.a = a; this.b = b; this.c = 0;
}

function make_booking( a, b, bookings ) {
  bookings.push( new booking( a, b ) );
  return bookings;
}

function some_function( x, y ) {
  var z;
  /* code goes here */
  return z;
}

function update_bookings( bookings ) {
  var i;
  for ( i = 0; i < bookings.length; i++ )
    if ( bookings[i].c == 0 )
      bookings[i].c = some_function( bookings[i].a, bookings[i].b );
  return bookings;
}

Of course, that code will get horribly distorted now, but whatever ;)

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#19559

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2013-05-01 22:12 +0000
Message-ID<kls3vj$6b7$4@dont-email.me>
In reply to#19555
On Wed, 01 May 2013 19:43:01 +0200, Evertjan. wrote:

> Daniel Pitts wrote on 01 mei 2013 in comp.lang.javascript:
> 
>> Alternatively, instead of using 1 base, use 0 base and when you need
>> "every third element", for (var i = 2; i < bookingArray.length; i+=3)
>> 
>> 
> for (var i = 0; i < bookingArray.length/3; i++)
>     x = bookingArray[i * 3 + 1];

I think the last "+ 1" should be +2

0 indexed, the first element he wants (with i = 0) is element [2] (the 
third element)

but x above will be element [1] when i = 0 ( 0 * 3 + 1 )

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#19569

From"Evertjan." <exxjxw.hannivoort@inter.nl.net>
Date2013-05-02 09:36 +0200
Message-ID<XnsA1B461B90ACBCeejj99@194.109.133.133>
In reply to#19559
Denis McMahon wrote on 02 mei 2013 in comp.lang.javascript:

> On Wed, 01 May 2013 19:43:01 +0200, Evertjan. wrote:
> 
>> Daniel Pitts wrote on 01 mei 2013 in comp.lang.javascript:
>> 
>>> Alternatively, instead of using 1 base, use 0 base and when you need
>>> "every third element", for (var i = 2; i < bookingArray.length; i+=3)
>>> 
>>> 
>> for (var i = 0; i < bookingArray.length/3; i++)
>>     x = bookingArray[i * 3 + 1];
> 
> I think the last "+ 1" should be +2
> 
> 0 indexed, the first element he wants (with i = 0) is element [2] (the 
> third element)
> 
> but x above will be element [1] when i = 0 ( 0 * 3 + 1 )

Indeed.

-- 
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)

[toc] | [prev] | [next] | [standalone]


#19584

FromScott Sauyet <scott.sauyet@gmail.com>
Date2013-05-02 08:52 -0700
Message-ID<c0affca3-9adb-40c0-bcdd-3222defbd338@a8g2000yqp.googlegroups.com>
In reply to#19552
Tony wrote:
> I use a 1 based array because I need to find each record that is a multiple
> of three later in the code.

That really should not cause any difficulty with standard arrays.
Others have already addressed this in their responses.


> bookingArray.sort(function (a, b)
>                    {
>                        var aObjectid = a.Objectid;
>                        var bObjectid = b.Objectid;
>
>                        var aFromtime = new Date(a.Fromtime);
>                        var bFromtime = new Date(b.Fromtime);
>
>                        if (aObjectid == bObjectid)
>                            return (aFromtime < bFromtime) ? -1 : (aFromtime
>  > bFromtime) ? 1 : 0;
>                        else
>                            return (aObjectid < bObjectid) ? -1 : 1;
>                    });

That sort function looks quite verbose.  (You might also want to look
at the FAQ section on posting [1] for the formatting preferences of
the group.)

You can probably achieve the same thing with this:

    bookingArray.sort(function(a, b) {
      return a.Objectid < b.Objectid ? -1 :
             a.Objectid > b.Objectid ? +1 :
             new Date(a.Fromtime) - new Date(b.Fromtime);
    });

And if the Objectid properties are numeric, you can get even simpler:


    bookingArray.sort(function(a, b) {
      return a.Objectid - b.Objectid ||
             new Date(a.Fromtime) - new Date(b.Fromtime);
    });

  -- Scott

[1] http://jibbering.com/faq/#posting

[toc] | [prev] | [next] | [standalone]


#19605

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-05-03 01:26 +0200
Message-ID<12786665.ZbpLptdNGN@PointedEars.de>
In reply to#19584
Scott Sauyet wrote:

> You can probably achieve the same thing with this:
> 
>     bookingArray.sort(function(a, b) {
>       return a.Objectid < b.Objectid ? -1 :
>              a.Objectid > b.Objectid ? +1 :
>              new Date(a.Fromtime) - new Date(b.Fromtime);

(The “+” in “+1” is a superfluous conversion operation; it is *not* a no-op.  
Also, few people know that “-1” actually is a “unary -” conversion operation 
on the primitive Number value 1.  See ES 5.1, §§ 11.4.6 and 11.4.7.)

Please do not write or suggest such code; it is a maintenance nightmare.  
Write such code if you want your colleagues to dislike you for it, put 
politely.  See also: <http://stackoverflow.com/q/14693135/855543>

The least you should do is using parentheses to group the expressions to 
make it easier to read and to debug, for example (preferred by me)

      return (a.Objectid < b.Objectid
        ? -1
        : (a.Objectid > b.Objectid
            ? 1
            : new Date(a.Fromtime) - new Date(b.Fromtime)));

or (preferred by others)

      return (a.Objectid < b.Objectid)
        ? -1
        : (a.Objectid > b.Objectid)
            ? 1
            : new Date(a.Fromtime) - new Date(b.Fromtime);

As the conversion to Date appears to be superfluous here¹, there is also 

  var comparator = jsx.array.getComparator(
    ["Objectid", "Fromtime"], {numeric: true});

  bookingArray.sort(comparator);

(see 
<http://PointedEars.de/websvn/filedetails.php?repname=JSX&path=/trunk/array.js>)

The least you should do is cache the comparator.

>     });
> 
> And if the Objectid properties are numeric, you can get even simpler:
> 
> 
>     bookingArray.sort(function(a, b) {
>       return a.Objectid - b.Objectid ||
>              new Date(a.Fromtime) - new Date(b.Fromtime);
>     });

Again, indicating the operator precedence is a good idea:

    bookingArray.sort(function (a, b) {
      return (a.Objectid - b.Objectid)
        || (new Date(a.Fromtime) - new Date(b.Fromtime));
    });

or (more efficient here)

    bookingArray.sort(function (a, b) {
      return (a.Objectid - b.Objectid) || (a.Fromtime - b.Fromtime);
    });

It should also be noted that using the “||” operator carries with it the 
internal conversion of the first operand to Boolean which may be more 
expensive than other approaches.

______
¹  However, this gives me the idea that it could be useful that
   jsx.array.getComparator() could also be passed a callback or constructor
   for each key, or all keys, whose return value would be used as operand
   in the comparison.  What do you think?
-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#19607

FromScott Sauyet <scott.sauyet@gmail.com>
Date2013-05-03 08:53 -0700
Message-ID<bd93fc08-185a-4614-91c2-a78ea5b6beaa@n11g2000yqe.googlegroups.com>
In reply to#19605
Thomas 'PointedEars' Lahn wrote:
> Scott Sauyet wrote:
>> You can probably achieve the same thing with this:
>
>>     bookingArray.sort(function(a, b) {
>>       return a.Objectid < b.Objectid ? -1 :
>>              a.Objectid > b.Objectid ? +1 :
>>              new Date(a.Fromtime) - new Date(b.Fromtime);
>
> (The “+” in “+1” is a superfluous conversion operation; it is *not* a no-op.

ACK.

But I choose to accept the very minor performance degradation in order
to keep the code more obvious, stressing that I'm returning a positive
number in one place and a negative in another.


> Also, few people know that “-1” actually is a “unary -” conversion operation
> on the primitive Number value 1.  See ES 5.1, §§ 11.4.6 and 11.4.7.)

What's your evidence for that?  I'm surprised to learn that few people
know that.  Do they expect it's simply part of the number literal
instead?


> Please do not write or suggest such code; it is a maintenance nightmare.
> Write such code if you want your colleagues to dislike you for it, put
> politely.  See also: <http://stackoverflow.com/q/14693135/855543>

While I do usually avoid nested ternary statements, this type of sort
function, because of their extreme simplicity, are often an exception.


> The least you should do is using parentheses to group the expressions to
> make it easier to read and to debug, for example (preferred by me)
>
>       return (a.Objectid < b.Objectid
>         ? -1
>         : (a.Objectid > b.Objectid
>             ? 1
>             : new Date(a.Fromtime) - new Date(b.Fromtime)));
>
> or (preferred by others)
>
>       return (a.Objectid < b.Objectid)
>         ? -1
>         : (a.Objectid > b.Objectid)
>             ? 1
>             : new Date(a.Fromtime) - new Date(b.Fromtime);


I find both of those harder to read than my suggestion.  Can you
suggest any objective criteria that makes those suggestions easier to
read or debug?


> As the conversion to Date appears to be superfluous here¹, there is also

I don't think so.  The OP didn't here specify the type of `Fromtime`,
but several recent posts from the OP discussed dates parsed out of
strings.  I remember for instance, something like "2013-05-03 11:00"
in a recent post.  Since we don't know that we can get rid of them, I
kept them in.


>   var comparator = jsx.array.getComparator(
>     ["Objectid", "Fromtime"], {numeric: true});
>
>   bookingArray.sort(comparator);
>
> (see
> <http://PointedEars.de/websvn/filedetails.php?repname=JSX&path=/trunk/...>)

That looks to be very useful.


> The least you should do is cache the comparator.

I'm not sure what you're suggesting.  Of course the comparator is
supplied as a single reference to the `sort` call.  And there was no
hint that the data needed to be sorted again later.  Of course if were
to be, the same function should probably be supplied to sort.  But
that's irrelevant to any issue at hand as far as I can see.

>> And if the Objectid properties are numeric, you can get even simpler:
>
>>     bookingArray.sort(function(a, b) {
>>       return a.Objectid - b.Objectid ||
>>              new Date(a.Fromtime) - new Date(b.Fromtime);
>>     });
>
> Again, indicating the operator precedence is a good idea:
>
>     bookingArray.sort(function (a, b) {
>       return (a.Objectid - b.Objectid)
>         || (new Date(a.Fromtime) - new Date(b.Fromtime));
>     });

Those parentheses neither add nor detract for me.  I certainly don't
object.  Stylistically, I prefer to keep the `||` on the first line,
but other than that, either one is fine, and I would probably choose
the parentheses if I hadn't dashed this off in three minutes.


> or (more efficient here)
>
>     bookingArray.sort(function (a, b) {
>       return (a.Objectid - b.Objectid) || (a.Fromtime - b.Fromtime);
>     });

See above.  I'm guessing that `Fromtime` is a string.


> It should also be noted that using the “||” operator carries with it the
> internal conversion of the first operand to Boolean which may be more
> expensive than other approaches.

Perhaps, but we all know about premature optimization...


> ______
> ¹  However, this gives me the idea that it could be useful that
>    jsx.array.getComparator() could also be passed a callback or constructor
>    for each key, or all keys, whose return value would be used as operand
>    in the comparison.  What do you think?

I'm not sure what you would mean by "or all keys" unless you mean for
each independently, but other than that, I can see that this would be
a useful option.  If the objects you want to sort have a property more
complex than a String or Number but that still has an intrinsic order,
it would be nice to be able to include that in your comparator.  But
rather than a callback/constructor, how about recursively applying
another comparator for that key?

  -- Scott

[toc] | [prev] | [next] | [standalone]


#19614

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-05-03 18:39 +0200
Message-ID<4320221.o7mTL0IePv@PointedEars.de>
In reply to#19607
Scott Sauyet wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Scott Sauyet wrote:
>>> You can probably achieve the same thing with this:
>>> bookingArray.sort(function(a, b) {
>>> return a.Objectid < b.Objectid ? -1 :
>>> a.Objectid > b.Objectid ? +1 :
>>> new Date(a.Fromtime) - new Date(b.Fromtime);
>>
>> (The “+” in “+1” is a superfluous conversion operation; it is *not* a
>> no-op.
> 
> ACK.
> 
> But I choose to accept the very minor performance degradation in order
> to keep the code more obvious, stressing that I'm returning a positive
> number in one place and a negative in another.

KISS: Numbers that have no negative sign are positive.  (Yes, I know about 
zero.)

>> Also, few people know that “-1” actually is a “unary -” conversion
>> operation on the primitive Number value 1.  See ES 5.1, §§ 11.4.6 and
>> 11.4.7.)
> 
> What's your evidence for that?

I remember to have observed this misconception several times before.

> I'm surprised to learn that few people know that.  Do they expect it's
> simply part of the number literal instead?

Apparently so.  I would expect many people to be surprised that

  var x = {-1: "foo"};

is syntactically wrong, while

  var x = {1: "foo"};

is correct, as it is somewhat counter-intuitive.  (A number is a number, 
isn't it?)

>> Please do not write or suggest such code; it is a maintenance nightmare.
>> Write such code if you want your colleagues to dislike you for it, put
>> politely.  See also: <http://stackoverflow.com/q/14693135/855543>
> 
> While I do usually avoid nested ternary statements, this type of sort
> function, because of their extreme simplicity, are often an exception.

Of course.  The problem is not the Conditional *Operator* (_not_ “ternary 
statements”).

>> The least you should do is using parentheses to group the expressions to
>> make it easier to read and to debug, for example (preferred by me)
>>
>> return (a.Objectid < b.Objectid
>>   ? -1
>>   : (a.Objectid > b.Objectid
>>       ? 1
>>       : new Date(a.Fromtime) - new Date(b.Fromtime)));
>>
>> or (preferred by others)
>>
>> return (a.Objectid < b.Objectid)
>>   ? -1
>>   : (a.Objectid > b.Objectid)
>>       ? 1
>>       : new Date(a.Fromtime) - new Date(b.Fromtime);
> 
> I find both of those harder to read than my suggestion.  Can you
> suggest any objective criteria that makes those suggestions easier to
> read or debug?

Yes.  As for reading, the parentheses make it clear what are either the 
conditional expressions or the conditions of those expressions.  As for 
debugging, each value is on its own line, therefore this code is easier to 
debug step-by-step with debuggers that debug by line instead of by 
expression.

>> var comparator = jsx.array.getComparator(
>> ["Objectid", "Fromtime"], {numeric: true});
>>
>> bookingArray.sort(comparator);
>>
>> (see
>> 
<http://PointedEars.de/websvn/filedetails.php?repname=JSX&path=/trunk/...>)
> 
> That looks to be very useful.

Thank you.

>> or (more efficient here)
>>
>> bookingArray.sort(function (a, b) {
>> return (a.Objectid - b.Objectid) || (a.Fromtime - b.Fromtime);
>> });
> 
> See above.  I'm guessing that `Fromtime` is a string.

Previous threads started by the same person on the same problem (BTW a bad 
idea) suggest that it is a Number value.

>> ______
>> ¹  However, this gives me the idea that it could be useful that
>> jsx.array.getComparator() could also be passed a callback or constructor
>> for each key, or all keys, whose return value would be used as operand
>> in the comparison.  What do you think?
> 
> I'm not sure what you would mean by "or all keys" unless you mean for
> each independently,

Currently you can configure the sort method (numeric or generic), sort order 
(ascending or descending), and strictness (strict or loose equality) of the 
sorting both for each key separately and for all keys specified in the 
factory call.  The same approach would be applied to the 
callback/constructor options.

> but other than that, I can see that this would be a useful option.

ACK

> If the objects you want to sort have a property more complex than a String
> or Number but that still has an intrinsic order, it would be nice to be
> able to include that in your comparator.  But rather than a
> callback/constructor, how about recursively applying another comparator
> for that key?

I do not see how this could work.  The elements of the Array are to be 
sorted by a property of the objects referred by the Array elements; the 
properties of the object's that are referred by the Array's elements are not 
to be modified.

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#19626

FromScott Sauyet <scott.sauyet@gmail.com>
Date2013-05-03 11:00 -0700
Message-ID<42a7e3a8-0fc0-4a5d-8809-312503f14f28@z10g2000yqd.googlegroups.com>
In reply to#19614
Thomas 'PointedEars' Lahn wrote:
> Scott Sauyet wrote:
>> Thomas 'PointedEars' Lahn wrote:

>>> or (more efficient here)
>
>>> bookingArray.sort(function (a, b) {
>>> return (a.Objectid - b.Objectid) || (a.Fromtime - b.Fromtime);
>>> });
>
>> See above.  I'm guessing that `Fromtime` is a string.
>
> Previous threads started by the same person on the same problem (BTW a bad
> idea) suggest that it is a Number value.

Interesting, as I had looked to other threads by the same poster and
drew a different conclusion.  Obviously if they are numbers, the Date
constructor is not necessary...


I'm guessing we're not going to come to any agreement on the code
style discussions, but I would like to address the following:


>>> ______
>>> ¹  However, this gives me the idea that it could be useful that
>>> jsx.array.getComparator() could also be passed a callback or constructor
>>> for each key, or all keys, whose return value would be used as operand
>>> in the comparison.  What do you think?
>
>> I'm not sure what you would mean by "or all keys" unless you mean for
>> each independently,
>
> Currently you can configure the sort method (numeric or generic), sort order
> (ascending or descending), and strictness (strict or loose equality) of the
> sorting both for each key separately and for all keys specified in the
> factory call.  The same approach would be applied to the
> callback/constructor options.

Yes, I did understand the code.  I just didn't see how supplying the
same constructor or callback for all properties would be useful.
Which means, I think, that I'm probably misunderstanding in general.

>> but other than that, I can see that this would be a useful option.
>
> ACK
>
>> If the objects you want to sort have a property more complex than a String
>> or Number but that still has an intrinsic order, it would be nice to be
>> able to include that in your comparator.  But rather than a
>> callback/constructor, how about recursively applying another comparator
>> for that key?
>
> I do not see how this could work.  The elements of the Array are to be
> sorted by a property of the objects referred by the Array elements; the
> properties of the object's that are referred by the Array's elements are not
> to be modified.

Perhaps I'm misunderstanding your suggestion.  My idea is probably
best given with an example.  If you had an array of objects structured
something like this:

    myCar {
      year: 2003,
      manufacturer: "Dodge",
      make: "Neon",
      color: "red",
      engine: {
        liters: 2.0,
        cylinders: 4
      },
      doors: 4
      // ...
    }

Then I might want to make a comparator with code something like this
(please forgive me if I misuse your API; I haven't actually tried it):

    var myComparator = jsx.array.getComparator([
      "year",
      "manufacturer",
      "model",
      {
        key: "engine",
        comparator: jsx.array.getComparator([
          "cylinders",
          "liters"
        ])
      }
    ]);

That internal `getComparator` call was what I was suggesting.  It
seems to me to be a great way of offereing additional flexibility.  Is
this similar to what you wanted to do?  Would it cover the same
ground?  It's clearly not as powerful as offering an arbitrary
function, but it might do much of what one would want to with such a
function, no?

  -- Scott

[toc] | [prev] | [next] | [standalone]


#19635 — Sorting arrays of objects (was: About keeping my array 1 based after having sorted it)

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-05-05 01:00 +0200
SubjectSorting arrays of objects (was: About keeping my array 1 based after having sorted it)
Message-ID<9570287.vLAVuxmI2c@PointedEars.de>
In reply to#19626
Scott Sauyet wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Scott Sauyet wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> ______
>>>> ¹  However, this gives me the idea that it could be useful that
>>>> jsx.array.getComparator() could also be passed a callback or
>>>> constructor for each key, or all keys, whose return value would be used
>>>> as operand in the comparison.  What do you think?
>>>
>>> I'm not sure what you would mean by "or all keys" unless you mean for
>>> each independently,
>>
>> Currently you can configure the sort method (numeric or generic), sort
>> order (ascending or descending), and strictness (strict or loose
>> equality) of the sorting both for each key separately and for all keys
>> specified in the factory call.  The same approach would be applied to the
>> callback/constructor options.
> 
> Yes, I did understand the code.  I just didn't see how supplying the
> same constructor or callback for all properties would be useful.
> Which means, I think, that I'm probably misunderstanding in general.

[This method, which is a (Function) factory, is now 
jsx.array.createComparator() to avoid confusion with getters.]

If the values of all (sort) keys are of the same type, and they are to be 
compared as if they were of another type, it should not be necessary to 
write

  var comparator = jsx.array.createComparator([
    {key: "x", callback: myConverter},
    {key: "y", callback: myConverter}
    {key: "z", callback: myConverter}
  ]);

instead of

  var comparator = jsx.array.createComparator(["x", "y", "z"], {
    callback: myConverter
  });

Same for “constructor” and “comparator”.  DRY.
 
>>> If the objects you want to sort have a property more complex than a
>>> String or Number but that still has an intrinsic order, it would be nice
>>> to be able to include that in your comparator.  But rather than a
>>> callback/constructor, how about recursively applying another comparator
>>> for that key?
>>
>> I do not see how this could work.  The elements of the Array are to be
>> sorted by a property of the objects referred by the Array elements; the
>> properties of the object's that are referred by the Array's elements are
>> not to be modified.
> 
> Perhaps I'm misunderstanding your suggestion.

ISTM you understand correctly.

> My idea is probably best given with an example.  If you had an array of
> objects structured something like this:
> 
>     myCar {
>       year: 2003,
>       manufacturer: "Dodge",
>       make: "Neon",
>       color: "red",
>       engine: {
>         liters: 2.0,
>         cylinders: 4
>       },
>       doors: 4
>       // ...
>     }
> 
> Then I might want to make a comparator with code something like this
> (please forgive me if I misuse your API; I haven't actually tried it):
> 
>     var myComparator = jsx.array.getComparator([
>       "year",
>       "manufacturer",
>       "model",
>       {
>         key: "engine",
>         comparator: jsx.array.getComparator([
>           "cylinders",
>           "liters"
>         ])
>       }
>     ]);
> 
> That internal `getComparator` call was what I was suggesting.  It
> seems to me to be a great way of offereing additional flexibility.

Yes, that is a Good Idea.  It is easier to implement and use, and more 
efficient than having the outer comparator iterate over subkeys.  
Implemented.

> Is this similar to what you wanted to do?  Would it cover the same
> ground?  It's clearly not as powerful as offering an arbitrary
> function, but it might do much of what one would want to with such a
> function, no?

[It turns out that one can eat this cake *and* have it.]

If the “callback” property is specified, the original sort value is 
converted by passing the value to it, and using its return value as the new 
sort value.

If the “constructor” (own) property is specified, the original or previous 
sort value is converted by passing it to the constructor, and using the 
returned object value as the new sort value.

If the “comparator” property is specified, it takes precedence over the 
default comparison, using the original sort value or one of the previous 
sort values.  If either the outer key is the last key, or if the inner 
comparator returns a value not equal to 0, the return value of the specified 
comparator is returned; otherwise the values of the next keys are 
considered.

That is,

  function Bar (baz)
  {
    this.baz = String(baz);
  }

  Bar.prototype.toString = function () {
    return this.baz;
  };

  function Baz (bla)
  {
    this.length = bla.length;
  }

  var foo = [
   {"bar": new Bar("burpbarbazbla")},
   {"bar": new Bar("foo")}
  ];

  var _createComparator = jsx.array.createComparator;

  foo.sort(_createComparator(["bar"], {
    callback: String,
    constructor: Baz,
    comparator: _createComparator(["length"], {numeric: true})
  }));

results in “foo” holding a reference to the equivalent of

  [
    {"bar": new Bar("foo")},
    {"bar": new Bar("burpbarbazbla")}
  ]

because:

  1a. String(new Bar("burpbarbazbla")) === "burpbarbazbla"
  1b. String(new Bar("foo"))           === "foo"
  2a. new Baz("burpbarbazbla") returns {length: 13} : Baz
  2b. new Baz("foo")           returns {length:  3} : Baz
  3a. new Baz("burpbarbazbla").length === 13
  3b. new Baz("foo").length           ===  3
  4.  3 < 13

The unit test is now available at 
<http://PointedEars.de/scripts/test/array>.

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#19641 — Re: Sorting arrays of objects (was: About keeping my array 1 based after having sorted it)

FromScott Sauyet <scott.sauyet@gmail.com>
Date2013-05-05 08:53 -0700
SubjectRe: Sorting arrays of objects (was: About keeping my array 1 based after having sorted it)
Message-ID<c6cce191-f2f8-487a-ae89-cb775395730a@r3g2000yqe.googlegroups.com>
In reply to#19635
Thomas 'PointedEars' Lahn wrote:
>Scott Sauyet wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> Scott Sauyet wrote:
>>>> Thomas 'PointedEars' Lahn wrote:
>>>>> ______
>>>>> ¹  However, this gives me the idea that it could be useful that
>>>>> jsx.array.getComparator() could also be passed a callback or
>>>>> constructor for each key, or all keys, whose return value would be used
>>>>> as operand in the comparison.  What do you think?
>
>>>> I'm not sure what you would mean by "or all keys" unless you mean for
>>>> each independently,
>
>>> Currently you can configure the sort method (numeric or generic), sort
>>> order (ascending or descending), and strictness (strict or loose
>>> equality) of the sorting both for each key separately and for all keys
>>> specified in the factory call.  The same approach would be applied to the
>>> callback/constructor options.
>
>> Yes, I did understand the code.  I just didn't see how supplying the
>> same constructor or callback for all properties would be useful.
>> Which means, I think, that I'm probably misunderstanding in general.
>
> [This method, which is a (Function) factory, is now
> jsx.array.createComparator() to avoid confusion with getters.]
>
> If the values of all (sort) keys are of the same type, and they are to be
> compared as if they were of another type, it should not be necessary to
> write
>
>   var comparator = jsx.array.createComparator([
>     {key: "x", callback: myConverter},
>     {key: "y", callback: myConverter}
>     {key: "z", callback: myConverter}
>   ]);
>
> instead of
>
>   var comparator = jsx.array.createComparator(["x", "y", "z"], {
>     callback: myConverter
>   });
>
> Same for “constructor” and “comparator”.  DRY.

I do (now) see that could be useful at times.  It's interesting how I
imagined almost exactly the same code and saw no reason for it, but as
soon as I saw it written out I could come up with possible uses!

If, for instance, `myConverter` converted Strings to Numbers or
changed the case of Strings, obviously it could be useful for a
comparator.  And if I can so easily come up with two such scenarios,
clearly there are many others.


>> [ ... ] My idea is probably best given with an example. [ ... ]
>>
>>     var myComparator = jsx.array.getComparator([
>>       "year",
>>       "manufacturer",
>>       "model",
>>       {
>>         key: "engine",
>>         comparator: jsx.array.getComparator([
>>           "cylinders",
>>           "liters"
>>         ])
>>       }
>>     ]);
>
>> That internal `getComparator` call was what I was suggesting.  It
>> seems to me to be a great way of offering additional flexibility.
>
> Yes, that is a Good Idea.  It is easier to implement and use, and more
> efficient than having the outer comparator iterate over subkeys.
> Implemented.

And it has the advantage that this internal comparator can be a
reference to one used elsewhere.


>> Is this similar to what you wanted to do?  Would it cover the same
>> ground?  It's clearly not as powerful as offering an arbitrary
>> function, but it might do much of what one would want to with such a
>> function, no?
>
> [It turns out that one can eat this cake *and* have it.]
>
> If the “callback” property is specified, the original sort value is
> converted by passing the value to it, and using its return value as the new
> sort value.
>
> If the “constructor” (own) property is specified, the original or previous
> sort value is converted by passing it to the constructor, and using the
> returned object value as the new sort value.
>
> If the “comparator” property is specified, it takes precedence over the
> default comparison, using the original sort value or one of the previous
> sort values.  If either the outer key is the last key, or if the inner
> comparator returns a value not equal to 0, the return value of the specified
> comparator is returned; otherwise the values of the next keys are
> considered.
> [ ... ]

This is extremely flexible.  I'm not sure how often I would need this
flexibility, but it's always nice to know when using an API that the
flexibility is there, so long as it doesn't overly complicate the API.

Nicely done.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#19633

FromDr J R Stockton <reply1300@merlyn.demon.co.uk.invalid>
Date2013-05-04 16:14 +0100
Message-ID<KBf07lIKXShRFw38@invalid.uk.co.demon.merlyn.invalid>
In reply to#19607
In comp.lang.javascript message <bd93fc08-185a-4614-91c2-a78ea5b6beaa@n1
1g2000yqe.googlegroups.com>, Fri, 3 May 2013 08:53:40, Scott Sauyet
<scott.sauyet@gmail.com> posted:

>Thomas 'PointedEars' Lahn wrote:
>> Scott Sauyet wrote:
>>> You can probably achieve the same thing with this:
>>
>>>     bookingArray.sort(function(a, b) {
>>>       return a.Objectid < b.Objectid ? -1 :
>>>              a.Objectid > b.Objectid ? +1 :
>>>              new Date(a.Fromtime) - new Date(b.Fromtime);
>>
>> (The “+” in “+1” is a superfluous conversion operation; it is *not* a no-op.
>
>ACK.
>
>But I choose to accept the very minor performance degradation in order
>to keep the code more obvious, stressing that I'm returning a positive
>number in one place and a negative in another.

A sensible system will handle those signs on reading the source or on
first executing the statement.  In any case, the time taken to do one of
those should be negligible in comparison with that taken to do the
function call and return.


>> Also, few people know that “-1” actually is a “unary -” conversion operation
>> on the primitive Number value 1.  See ES 5.1, §§ 11.4.6 and 11.4.7.)
>
>What's your evidence for that?  I'm surprised to learn that few people
>know that.  Do they expect it's simply part of the number literal
>instead?

A script engine is required to give the results which would be given if
the specification was followed literally.  If there is a formal
requirement to follow the specification literally, it will be ignored in
actual browsers where thought beneficial to do so.


-- 
 (c) John Stockton, nr London, UK.   E-mail, see Home Page.    Turnpike v6.05.
 Website  <http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
 PAS EXE etc. : <http://www.merlyn.demon.co.uk/programs/> - see in 00index.htm
 Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web