Array sorteren

Status
Niet open voor verdere reacties.

Creatorus

Gebruiker
Lid geworden
28 nov 2011
Berichten
10
Beste mensen,

ik zit met een probleem binnen een stuk javascript code, zoals je misschien al verwachte aangezien ik hier een vraag post.
Ik heb een stuk code waar een array uit gerold komt met als array keys namen, en als values komen er getallen uit. Nu wil ik de array sorteren op de values maar kan hier niets over vinden.
Weten jullie misschien hoe ik dit het best kan doen

Alvast bedankt
 
sorteren gaat met sort(). Arrays worden standaard gesorteed op value...

[js]var spul = [];

spul['test'] = 42;
spul['bbq'] = 1337;
spul['sauce'] = 512;

spul.sort(); // geeft [1337, 512, 42][/js]


bedoel je dit?...
 
@That Guy

ik ken de .sort() functie, alleen dan verdwijnen de key's die ik heb toegewezen. En dat is nu juist niet de bedoeling
 
Ah, op die manier.


Nou, het punt is dat arrays eigenlijk helemaal geen 'keys' hebben. Arrays hebben alleen een index nummer. In Javascript kan je het wel doen, zeker, maar eigenlijk misbruik je het dan een beetje. Wat je eigenlijk doet is een object aanmaken. Punt is alleen dat je in objecten geen specifieke volgorde hebt zoals je dat in arrays hebt.

[js]var spul = {}; // of: new Object()

spul['test'] = 1337; // of: spul.test = 1337;[/js]

In ieder geval, wat je zoekt is de zin Javascript associative array sort. Google helpt verder:




:thumb:
 
Laatst bewerkt:
Stel dat ik er dan een object van maak, kan ik daar dan ook dynamisch velden aan toevoegen? zoals bij jou 'test' maar dit word in mijn script gedetineerd door een andere variabele.
 
In principe maakt het niet uit of je een object of een array gebruikt*, want het resultaat is hetzelfde; het ging even om het idee. Maar ja, dat is de pracht van Javascript, je kan het veranderen wanneer je wilt!

[js]var spul = []; // of: {}

spul['iets'] = 4;
spul['bbq'] = 1337;

// ...

spul.iets = 9; // verander spul['iets'] naar 9 (was 4)
spul['iets'] = 6; // verander spul['iets'] naar 6 (was 9)


// het kan zelfs zo:

var kijkmij = 'iets';
spul[kijkmij] = 12; // verander spul['iets'] naar 12 (was 6)[/js]


:thumb:




* in dit geval, want als je er een object van maakt kan je niet methodes als .sort() en properties als .length gebruiken - die zijn van Array.
 
Laatst bewerkt:
maar als ik dan de sort functie toepas op de array, dan worden de "namen" die ik erin geplaatst heb als identifier veranderderd in cijfers, en dat moet ik dan weer niet hebben. Hoe kom ik hier omheen of onderuit. Of kan wat ik wil niet?
 
Ja, dat klopt, daarom moet je wat speciale code gaan gebruiken die hier omheen gaat. Zie de links bij post #4. Hier is een kort (werkend) stukje voorbeeld uit een van de links:

[js]var a = [];

a['b'] = 1337;
a['z'] = 42;
a['a'] = 3;

var b = [];

for(var k in a)
{
b.push(k); // b = ['b', 'z', 'a']
}

b.sort(); // b = ['a', 'b', 'z'];

for(var i = 0; i < b.length; ++i)
{
alert(b + ' heeft de value ' + a[b]);
// a[b] betekent: in array a, wat is de waarde van b?
// b is toevallig de key (string) op gesorteerde volgorde
// a[b] bij bijvoorbeeld i = 0 betekent dus a['a'], wat 3 is.
}

/*
geeft:

a heeft de value 3
b heeft de value 1337
z heeft de value 32
*/[/js]
 
Laatst bewerkt:
We komen dichter in de buurt. De situatie die ik heb is bijvoorbeeld
--
p['a'] = 9;
p['b'] = 6;
p['c'] = 0;
p['d'] = 2;
--
en dit moet dan worden sorteert worden als
--
a, b, d, c
--
 
Ah, nu ik het terug lees is het allemaal een beetje door de war gelopen.


In ieder geval: het punt is een beetje dat het sorteren nogal nutteloos is. Echter, je kan door een object heenlopen met for x in y; dat is standaard op alfabetische volgorde. Omdat je in de array de index-nummers hebt verwisseld met strings - het is dus een object geworden - is het niet nuttig om te sorteren.

Mocht je echter willen sorteren om zo correct door de letters heen te lopen, kan je wat vogelen met een loop. Neem bijvoorbeeld zoiets:
[js]function mahsort(arr)
{
var key, value,
tuples = [],
ret = [],
len = 0;

for(key in arr)
{
tuples.push([key, arr[key]]);
len++;
}

tuples.sort(function(a, b)
{
return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0;
});

for(i = 0; i < len; i++)
{
key = tuples[0];
value = tuples[1];

// doe iets nuttigs
alert(key + ' - ' + value);
}
}[/js]
[js]var p = [];

p['a'] = 9;
p['b'] = 6;
p['c'] = 0;
p['d'] = 2;


mahsort(p);[/js]

dit geeft als output in een alert:
Code:
a - 9
b - 6
d - 2
c - 0

nogmaals, de functie is waarschijnlijk nogal overbodig als je maar met 1 array werkt; het kan een stuk korter en sneller als je 'm gewoon om de array heen bouwt.



:thumb:
 
Laatst bewerkt:
DAT is precies wat ik zocht, Heel erg bedankt daarvoor.
Dan heb ik nu nog een vraag. Als de waardes van 2 opeenvolgende velden gelijk zijn, kan ik deze dan ook nog sorteren op een 3e waarde. Dus stel dat het er zo uitziet nu
--
p[a] = 3;
p = 3;
p[c] = 0;
p[d] = 9;

g[a] = -1;
g = 3;
g[c] = 0;
g[d] = -5;
--
dat de volgorde dan wordt
--
p[d] = 9;
p = 3;
p[a] = 3;
p[c] = 0;
--
Ik hoop dat dit ook nog kan
 
Eh, dus bij gelijke waardes moet je kijken naar een andere array, en daar de volgorde uit ophalen? Well, het kan zeker, maar op het moment kan ik even geen effectieve manier bedenken. Je kan in de .sort(Function); call de functie veranderen, maar de enige parameters doe deze krijgt zijn de waardes (a en b) en niet de keys, anders kon je simpelweg een g[x] en g[y] vergelijken.

Ik zal er even over nadenken, en een reactie plaatsen als ik iets slims heb bedacht.
 
Je kan in de .sort(Function); call de functie veranderen, maar de enige parameters doe deze krijgt zijn de waardes (a en b) en niet de keys, anders kon je simpelweg een g[x] en g[y] vergelijken.
Die heb je toch juist wel? Je vergelijkt immers tupels, waarbij de key voor het element waar het om draait op positie 0 staat.

[JS]function mahsort(arr, arr2) {
var key, value,
tuples = [],
ret = [],
len = 0;

for(key in arr)
{
tuples.push([key, arr[key]]);
len++;
}

tuples.sort(function(a, b) {
return a[1] < b[1] ? 1 : (a[1] > b[1] ? -1 : (arr2[a[0]] < arr2[b[0]] ? 1 : (arr2[a[0]] > arr2[b[0]] ? -1 : 0)));
});

for(var i = 0; i < len; i++)
{
key = tuples[0];
value = tuples[1];

// doe iets nuttigs
alert(key + ' - ' + value);
}
}[/JS]

[JS]var p = {
a: 3,
b: 3,
c: 0,
d: 9
};
var g = {
a: -1,
b: 3,
c: 0,
d: -5
};
mahsort(p, g);[/JS]
 
Ik bedoel het eigenlijk anders, dat omdat er bij p[a] en p beide een score van 3 staat dat p boven p[a] staat omdat q>q[a]
 
Dat is wat er gebeurt toch? Hiermee worden de elementen van p in deze volgorde gepresenteerd: p[d], p, p[a] en p[c]. In welk opzicht is dat anders dan wat je zou willen hebben?
 
Mijn script deed dit:

[js] tuples.sort(function(a, b)
{
return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0;
});[/js]

ofwel: sorteer op de waardes van de array. Het stukje van Robin S:

[js] tuples.sort(function(a, b) {
return a[1] < b[1] ? 1 : (a[1] > b[1] ? -1 : (arr2[a[0]] < arr2[b[0]] ? 1 : (arr2[a[0]] > arr2[b[0]] ? -1 : 0)));
});[/js]

uitgeschreven staat hier:

[js]if(a[1] < b[1])
{
return 1; // a < b
}else{

if(a[1] > b[1])
{
return -1; // b > a
}else{

// alles vanaf hier gebeurt als a == b

if(arr2[a[0]] < arr2[b[0]])
{
return 1; // andere array a < andere array b
}else{

if(arr2[a[0]] > arr2[b[0]])
{
return -1; // andere array a > andere array b
}else{
return 0; // a == b EN andere array a == andere array b
}
}
}
}[/js]

ofwel: sorteer op waardes van de array (de 1e twee if's). Als het toevallig gelijk is, check dan de waardes in de 2e array (3e en 4e if). De a[0] en b[0] zijn namelijk de strings ('a' en 'b' etc).





Als ik Robin S' code uitvoer krijg ik netjes de goede volgorde! :thumb:
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan