sort() a string by a number within the string?

D

David

Hi all,

I have an array of strings. For example...

[0] = "entry1 first entry";
[1] = "entry2 second entry";
[2] = "entry3 third entry";
etc...

How can I sort this array by the number after "entry"?

David
 
D

David

I should have stated that the array may become mixed when some processing in
the script is changed. For example..

[0] = "entry1 first entry";
[1] = "entry3 third entry";
[2] = "entry2 second entry";
etc...

So I need to straighten it out, sort() it, to be in numerical order by the
number after the word "entry" so that the end result is like this..

[0] = "entry1 first entry";
[1] = "entry2 second entry";
[2] = "entry3 third entry";
etc...

David
 
M

Martin Honnen

David said:
I should have stated that the array may become mixed when some processing in
the script is changed. For example..

[0] = "entry1 first entry";
[1] = "entry3 third entry";
[2] = "entry2 second entry";

An array object has a sort method to which you can pass your own
comparison function if needed that compares what you want to compare e.g.

var a = new Array();
a[0] = "entry1 first entry";
a[1] = "entry3 third entry";
a[2] = "entry2 second entry";

var result = a.join('|');

a.sort(function (el1, el2) {
var pattern = /^entry(\d+)/g;
var n1, n2;
pattern.lastIndex = 0;
var match1 = pattern.exec(el1);
if (match1) {
n1 = Number(match1[1]);
}
pattern.lastIndex = 0;
var match2 = pattern.exec(el2);
if (match2) {
n2 = Number(match2[1]);
}
if (typeof n1 != 'undefined' && typeof n2 != 'undefined') {
return n1 - n2;
}
else {
// no numbers found
// could throw an error
return -1;
}
});

result += '\r\n\r\n' + a.join('|');

alert(result);


Documentation is here:
<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:sort>
 
D

David

Martin Honnen said:
An array object has a sort method to which you can pass your own
comparison function if needed that compares what you want to compare e.g.

var a = new Array();
a[0] = "entry1 first entry";
a[1] = "entry3 third entry";
a[2] = "entry2 second entry";

var result = a.join('|');

a.sort(function (el1, el2) {
var pattern = /^entry(\d+)/g;
var n1, n2;
pattern.lastIndex = 0;
var match1 = pattern.exec(el1);
if (match1) {
n1 = Number(match1[1]);
}
pattern.lastIndex = 0;
var match2 = pattern.exec(el2);
if (match2) {
n2 = Number(match2[1]);
}
if (typeof n1 != 'undefined' && typeof n2 != 'undefined') {
return n1 - n2;
}
else {
// no numbers found
// could throw an error
return -1;
}
});

result += '\r\n\r\n' + a.join('|');

alert(result);


Documentation is here:
<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:sort>


Thanks Martin, that worked quite nicely :)

David
 
M

Mick White

David said:
I have an array of strings. For example...

[0] = "entry1 first entry";
[1] = "entry2 second entry";
[2] = "entry3 third entry";
etc...

How can I sort this array by the number after "entry"?

stringArray=
["entry1 first entry","entry2 second entry","entry3 third entry"]
function davidSort(a,b){
return a.split(" ")[0].replace(/[^\d]/g,"")-
b.split(" ")[0].replace(/[^\d]/g,"");
}
alert(stringArray.sort(davidSort).join("\n"))

Mick
 
D

David

Mick White said:
stringArray=
["entry1 first entry","entry2 second entry","entry3 third entry"]
function davidSort(a,b){
return a.split(" ")[0].replace(/[^\d]/g,"")-
b.split(" ")[0].replace(/[^\d]/g,"");
}
alert(stringArray.sort(davidSort).join("\n"))

Mick


Very elegant and simple. Thanks Mick, it works great.

David
 
D

Dr John Stockton

JRS: In article <OXkWe.25286$8h6.11450@trnddc09>, dated Thu, 15 Sep
Mick White said:
stringArray=
["entry1 first entry","entry2 second entry","entry3 third entry"]
function davidSort(a,b){
return a.split(" ")[0].replace(/[^\d]/g,"")-
b.split(" ")[0].replace(/[^\d]/g,"");
}
alert(stringArray.sort(davidSort).join("\n"))

Mick


Very elegant and simple. Thanks Mick, it works great.


Like Martin Honnen's method, it will be unnecessarily show for large
arrays. The expected number of calls of davidSort is greater than o(N)
for an N-element array, and each call performs two non-trivial
manoeuvres.

For efficiency, do a first pass of o(N) which converts each element to
something with the sort key also at the front, do a default (string)
sort o(>N), then strip the key taking o(N). The default comparison
will, I expect, be quicker than using the fastest possible sort
function.


The OP did not unambiguously specify the task : he wrote "number" which
sometimes means "digit" and sometimes "[sign]digit(s)" etc.

You and Martin have, I think, both assumed "number" to mean "string of
decimal digits", which is probably what the OP meant. Neither of you, I
suspect, handle the general case of a number in any form S acceptable to
Number(S).

David, please trim your quotes : see newsgroup FAQ.
 
M

Mick White

Dr said:
JRS: In article <OXkWe.25286$8h6.11450@trnddc09>, dated Thu, 15 Sep
:

stringArray=
["entry1 first entry","entry2 second entry","entry3 third entry"]
function davidSort(a,b){
return a.split(" ")[0].replace(/[^\d]/g,"")-
b.split(" ")[0].replace(/[^\d]/g,"");
}
alert(stringArray.sort(davidSort).join("\n"))

Mick


Very elegant and simple. Thanks Mick, it works great.



Like Martin Honnen's method, it will be unnecessarily show for large
arrays. The expected number of calls of davidSort is greater than o(N)
for an N-element array, and each call performs two non-trivial
manoeuvres.

For efficiency, do a first pass of o(N) which converts each element to
something with the sort key also at the front, do a default (string)
sort o(>N), then strip the key taking o(N). The default comparison
will, I expect, be quicker than using the fastest possible sort
function.

The point of my reply was that he needs to extract from the object that
portion of which he wants to compare. I'm not quite following what
you're saying, I'd love to see a sample.
Of course, the ideal solution is to create the array object correctly in
the first place.
The OP did not unambiguously specify the task : he wrote "number" which
sometimes means "digit" and sometimes "[sign]digit(s)" etc.

Trivial to do, though "entry-1" is unlikely.
You and Martin have, I think, both assumed "number" to mean "string of
decimal digits", which is probably what the OP meant. Neither of you, I
suspect, handle the general case of a number in any form S acceptable to
Number(S).

Yes I did
Mick
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated
Fri, 16 Sep 2005 21:23:02, seen in Mick White
Dr John Stockton wrote:

The point of my reply was that he needs to extract from the object that
portion of which he wants to compare.

In fact, one does not *need* to *extract* it.

I'm not quite following what
you're saying, I'd love to see a sample.

Let T be a string such as "entry1 first entry" matching the first
RegExp:
T = T.replace(/^(\D*)(\d+)/, "00000$2$1$2")
T = T.replace(/^(.*)(\d{6})/, "$2")
The combination of those adds the value of the first "number" part, as a
SIX-digit string, to the front of T, now "000001entry1 first entry".
There may be better ways.

If the elements of the array are all treated as T there is, the array
can now be sorted by the default sort, and the original elements can
easily be recovered by substringing.

For this to be worthwhile, the array must be sufficiently large, and
that can only be determined by test since it depends on the browser and
script coding.
 
D

David

The OP did not unambiguously specify the task : he wrote "number" which
sometimes means "digit" and sometimes "[sign]digit(s)" etc.
You and Martin have, I think, both assumed "number" to mean "string of
decimal digits", which is probably what the OP meant. Neither of you, I
suspect, handle the general case of a number in any form S acceptable to
Number(S).


Mick is correct and his solution worked just fine. By number I did mean that
I wanted to sort by the decimal digit or numeral.

Thank you all for your helpful input.

David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top