2-dimensionale array sorteren

Pagina: 1
Acties:

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Topicstarter
Nee, geen vraag, maar gewoon een mooi stukje code dat ik wel wil delen.
Stel, je hebt een 2-dimensionale array die je op een willekeurig element wilt sorteren:
code:
1
2
3
4
5
6
7
8
var topic = new Array();
topic[0] = new Array(20020604101832, 'gnoe');
topic[1] = new Array(20020604171547, 'crisp');
topic[2] = new Array(20020604132617, 'pelle');
topic[3] = new Array(20020604225456, 'clay');
topic[4] = new Array(20020605030238, 'cutter');
topic[5] = new Array(20020604011142, 'fietstas');
topic[6] = new Array(20020605051628, 'woei');

Voor zover ik weet kan je hier geen gewone sort() op loslaten, dus heb ik de volgende code bedacht (bubble-sort):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function _copy() {

  var temparray = new Array();
  for (var i = 0; i < this.length; i++) {
    temparray[i] = this[i];
  }
  return temparray;

}
Array.prototype.copy = _copy;

function _sorta(el, ad) {

  var i;
  var s = 0;
  var l = 0;
  var r = this.length - 1;
  var d = 1;
  var n = (ad == 'a')? 1:-1;

  while (l*d < r*d) {

    for (i = l; d*i < d*r; i+=d) {

    if ((this[i][el] > this[i+d][el] && (d*n==1))
     || (this[i][el] < this[i+d][el] && (d*n==-1))) {

      temparray = this[i].copy();
      this[i] = this[i+d].copy();
      this[i+d] = temparray.copy();
      s=i;

    }

    }

    r = l;
    l = s;
    d *= -1;

  }

}
Array.prototype.sorta = _sorta;

Nu kan je de array sorteren mbv array.sorta([element], [volgorde]).
Wil je op timestamp aflopend sorteren doe je dus:
code:
1
topic.sorta(0, 'd');

Wil je op usernaam oplopend sorteren doe je:
code:
1
topic.sorta(1, 'a');

Hier nog een stukje code om de gesorteerde array naar scherm te schrijven:
code:
1
2
3
4
5
6
7
8
9
10
11
for (i = 0; i < topic.length; i++) {

  for (n = 0; n < topic[i].length; n++) {

    document.write(topic[i][n] + ', ');

  }

  document.write('<br>');

}

Als iemand nog makkelijkere/snellere/betere methodes weet, dan hou ik me aanbevolen! :)

Intentionally left blank


Verwijderd

Als ik dit zo snel even zie, is het meer iets om een array met objecten te sorteren...eigenlijk wordt namelijk alleen topic gesorteerd en niet bijvoorbeeld topic[0] en topic[1].

Scott Andrew heeft een elegante manier om arrays met objecten te sorteren op object-properties.
http://www.scottandrew.com/weblog/000179

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 29-08 19:47

Bosmonster

*zucht*

Scott emuleert het normale Java-gedrag zeg maar en schrijft een soort interface. That's the way to go :)

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Topicstarter
Op dinsdag 04 juni 2002 16:23 schreef Blues het volgende:
Als ik dit zo snel even zie, is het meer iets om een array met objecten te sorteren...eigenlijk wordt namelijk alleen topic gesorteerd en niet bijvoorbeeld topic[0] en topic[1].

Scott Andrew heeft een elegante manier om arrays met objecten te sorteren op object-properties.
http://www.scottandrew.com/weblog/000179
En zo leer je weer wat; wist niet dat dat ook zo kon! :)
Ik was al heel blij dat ik op bovenstaand idee was gekomen, en mijn oude basic/pascal bubblesort routine uiteindelijk in effectief 10 coderegels javascript wist om te zetten :)

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Topicstarter
En nu heb ik dan toch een vraagje :)

Ik krijg zeg maar mijn timestamps and usernames in een comma-seperated string binnen:
code:
1
2
var timestamps = '20020604101832,20020604171547,20020604132617';
var usernames = 'gnoe,crisp,pelle';

Nu wil ik dit dus in een Array zetten dmv string.split(',').
Alleen als ik nu properties aanmaak bijvoorbeeld op deze manier:
code:
1
2
3
var topics = new Array();
topics.timestamp = new Array();
topics.username = new Array();

En ik doe:
code:
1
2
topics.timestamp = timestamps.split(',');
topics.username = usernames.split(',');

Dan wordt dit zeg maar mijn array:
code:
1
2
3
4
5
6
topics.timestamp[0] = 20020604101832
topics.timestamp[1] = 20020604171547
topics.timestamp[2] = 20020604132617
topics.username[0] = 'gnoe'
topics.username[1] = 'crisp'
topics.username[2] = 'pelle'

Wel logisch op zich, maar ik wil dit hebben:
code:
1
2
3
4
5
6
topics[0].timestamp = 20020604101832
topics[0].username = 'gnoe'
topics[1].timestamp = 20020604171547
topics[1].username = 'crisp'
topics[2].timestamp = 20020604132617
topics[2].username = 'pelle'

zodat als ik de topics array sorteer op een property, dat alles blijft kloppen.

Kan ik dit nu ook op een makkelijke/slimme manier voor elkaar krijgen?

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Topicstarter
Nog een leuke trouwens:

de volgende functie:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
var track = new Array();
function _checktrack(topicid) {

  for (var i=0; i < this.length; i++) {

    if (this[i] == topicid) return i;

  }

  return -1;

}
Array.prototype.checktrack = _checktrack;

werkt prima als ik in welke functie dan ook dit gebruik:
code:
1
var i = track.checktrack(topicid);

Vervang ik echter de prototype door door dit:
code:
1
track.checktrack = _checktrack;

dan werkt het in de ene functie wel goed, maar binnen een andere functie (exact dezelfde syntax) krijg ik: object doesn't support this property or method :?

Intentionally left blank


  • oh,when?
  • Registratie: April 2000
  • Niet online

oh,when?

...

Op dinsdag 04 juni 2002 22:55 schreef crisp het volgende:

Wel logisch op zich, maar ik wil dit hebben:

Kan ik dit nu ook op een makkelijke/slimme manier voor elkaar krijgen?
but yes ofcourse..
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function user( t, u ) {
    this.timestamp = t;
    this.username = u;
}

var timestamps = '20020604101832,20020604171547,20020604132617';
var usernames = 'gnoe,crisp,pelle';

var ts = timestamps.split(',');
var un = usernames.split(',');

var topics = new Array();

if ( ts.length == un.length ) {
    for ( var i = 0; i < ts.length; ++i ) {
        topics[i] = new user(ts[i],un[i]);  
    }
}

alert(topics[0].timestamp);

:)

"You're only as good, as what you did last week."


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Topicstarter
Op woensdag 05 juni 2002 00:31 schreef oh,when? het volgende:

[..]

but yes ofcourse..
...
:)
Thankx! Ik had zelf inmiddels het volgende bedacht:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var topic = new Array();
function _addtotopic(ar, el) {
  for (var i = 0; i < ar.length; i++) {
    if (!this[i]) this[i] = new Array();
    this[i][el] = ar[i];
  }
}
topic.addtotopic = _addtotopic;

var timestamps = '20020604101832,20020604171547,20020604132617';
var usernames = 'gnoe,crisp,pelle';

topic.addtotopic(timestamps.split(','), 'timestamp');
topic.addtotopic(usernames.split(','), 'username');

Moet alleen nog even testen of dit werkt....

edit:

Met een kleine aanpassing werkt dit ook :)
Nu maar hopen dat ik niet weer gedonder krijg omdat ik de method aan het topic object koppel en niet aan de Array class...

Intentionally left blank


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

crisp:
Vervang ik echter de prototype door door dit:
code:
1
track.checktrack = _checktrack;

dan werkt het in de ene functie wel goed, maar binnen een andere functie (exact dezelfde syntax) krijg ik: object doesn't support this property or method :?
Da's logisch. Je geeft dan namelijk voor het object (de instantie) aan wat 'checktrack' moet zijn, in plaats van voor de class (waar je instanties van maakt)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Topicstarter
Op woensdag 05 juni 2002 10:31 schreef drm het volgende:

[..]

Da's logisch. Je geeft dan namelijk voor het object (de instantie) aan wat 'checktrack' moet zijn, in plaats van voor de class (waar je instanties van maakt)
Ik snap wat je bedoelt, maar het probleem is dus dat ik de functie checktrack alleen maar gebruik voor de array track.
Inmiddels heb ik de _checktrack functie verder naar boven verplaatst in de source en werkt het wel goed :?
Enfin allen bedankt, ik ben al weer een stuk verder! :)

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Topicstarter
Het sorteren heb ik uiteindelijk toch maar anders gedaan, en is een factor 15 sneller als de eerder geposte code :)
Behalve als er geen mutaties nodig zijn, dan is mijn code 2x zo snel >:)

Ik maak gebruik van een pointer-array die ik sorteer inplaats van de array zelf te muteren, en lees de array vervolgens uit via de pointer-array. Dit wordt natuurlijk steeds effectiever naarmate je array meer properties heeft:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var el = 'timestamp'; // property to sort on
var ad = 1; // 1 for ascending, -1 for descending

var index = new Array();
for (var i = 0; i < topics.length; i++) {
  index[i] = i;
}
index.sort(compare);

for (var i = 0; i < index.length; i++) {
  document.write(topics[index[i]].timestamp + '<br />');
}

function compare(a, b) {
  if (topics[a][el] < topics[b][el]) {
    return ad*-1;
  } else if (topics[a][el] > topics[b][el]) {
    return ad;
  } else {
    return 0;
  }
}

Ergo: echt handig die compare functie voor de sort() methode :)

Intentionally left blank

Pagina: 1