Arrays og String.split()

Kategori: Tips og tricks | Kommentarer (5)
Gemt: 2007-01-30 14:29


Jeg kan lige så godt sige det som det er, jeg elsker arrays!
Kan noget ikke laves ved hjælp af et loop, så bør man måske overveje om det i det hele taget er værd at lave?

Spøg til side, jeg er faktisk vild med arrays og i går havde jeg en problemstilling hvor de, sammen med den ligeledes klassiske String.split(), var den perfekte løsning.

Jeg sidder i øjeblikket og arbejder på en kampagne for en unavngiven større dansk radiostation som gå i luften 1. februar.
For at høre radio skal man kende frekvensen på det man ønsker at lytte til, og modsat internettet hvor alle skal indtaste den samme adresse for at finde det samme indhold, så er det en helt anden historie når vi snakker FM frekvenser.

I dette tilfælde er der cirka 25 forskellige frekvenser der hver især dækker forskellige dele af landet.
For at gøre det nemt for brugerne er vi derfor i gang med at producere noget materiale der blandt andet indeholder en lille funktion, hvor man ved at indtaste sit postnummer får en radiofrekvens retur.

Til det formål har jeg modtaget en frekvens liste der starter sådan her:

By Frekvens Postnumre
København 91,4 555-3670
Sydsjælland 103,9 4000-4983
Fyn 93,4 5000-5985
Middelfart 106,6 5500

Og sådan fortsætter den ellers derudaf, intet odiøst i det.

Men, bemærkede du den sidste på listen, Middelfart?
Her er der ikke tale om et postnummer interval, men derimod om et specifikt postnummer, som ovenikøbet er inde i et allerede eksisterende interval, der har en anden frekvens.
Med andre ord, så ville jeg få et positivt match både hvis jeg lavede en funktion der testede om 5500 var mellem 5000-5985, samt hvis jeg lavede en der testede om 5500 var lig med 5500.

I det her tilfælde blev det besluttet, at hvis et postnummer har et præcist match, så har det match højere prioritet end hvis det er med i et interval.
Løsningen er således først at tjekke om der er et præcist match, og hvis der ikke er det, så tjekke om det er med i et interval.

Okay, nu har vi tænkt de mulige scenarier og problemstillinger igennem, så nu er det tid til at kode en løsning.

Første skridt er at lave vores tabel om til nogle data som man kan arbejde videre med.
I mange tilfælde ville man nok vælge at bruge XML, men da dataene i dette tilfælde skal bruges i et banner, er det en stor fordel hvis man kan undgå at loade noget eksternt, så derfor er det simpelthen hardcodet:
(Bynavnene skulle ikke bruges i dette tilfælde, derfor er de udeladt)

var arrFrek1:Array = new Array(); //Specifikke postnumre
var arrFrek2:Array = new Array(); //Intervaller

arrFrek1.push("5500@106,6");

arrFrek2.push("555:3650@91,4");
arrFrek2.push("4000:4983@103,9");
arrFrek2.push("5000:5985@93,4");

Push funktionen gør simpelthen det at den indsætter den pågældende tekststreng som et nyt punkt i enden af array’et.
Så, nu har vi to arrays, et med specifikke postnumre og et med postnummerintervaller.

Næste skridt er så at lave en funktion der løber de to arrays igennem for at finde frekvensen til et bestemt postnummer.
Jeg har forsøgt at forklare koden med kommentarer i koden:

function findFrekvens(Frekvens:Number):String {
	var arrTemp1:Array = new Array();
	var arrTemp2:Array = new Array();
	var frekvensOutput:String = undefined; //Den streng funktionen skal returnere

	for(i = 0; i < arrFrek1.length; i++) {
		arrTemp1 = arrFrek1[i].split("@"); //Splitter data strengen, så vi kan teste på postnummeret
		if(Number(arrTemp1[0]) == Frekvens) { //Er postnummeret lig med postnummeret for denne frekvens
			frekvensOutput = arrTemp1[1]; //Gemmer frekvensen
			break; //Stopper loopet
		}
	}

	if(frekvensOutput == undefined) { //Blev der fundet et match i det første loop?
		for(i = 0; i < arrFrek2.length; i++) {
			arrTemp1 = arrFrek2[i].split("@");
			arrTemp2 = arrTemp1[0].split(":");
			if(Frekvens >= Number(arrTemp2[0]) && Frekvens <= Number(arrTemp2[1])) { //Er postnummeret i intervallet
				frekvensOutput = arrTemp1[1];
				break;
			}
		}
	}

	return frekvensOutput; //Returnerer den fundne frekvens, eller undefined hvis ingen blev fundet
}

Voila, ved hjælp at et par arrays eller fire samt nogle splits, så fik vi lavet en lille simpel funktion.

Hvis det var en funktion der ville blive kaldt mange gange af den samme bruger, så kunne man sagtens vælge at definere data anderledes, så man ikke brugte unødig CPU på at gentage de mange splits, så ville det se sådan her ud:

arrFrek2.push(new Array(new Array("5000","5985"),"93,4");

Men, i dette tilfælde har jeg prioriteret overskueligheden højere, særligt da 9 ud af 10 brugere kun vil kalde funktion én gang.

Så, det var et bud fra min side på en løsning af en meget specifik problemstilling, håber det kan bruges til noget.

NB: Har set at kodedelen bryder designet lidt, men syntes at det var vigtigt at den var rigtigt formatteret for at give et bedre overblik, må lige se om jeg kan få opdateret min template på et tidspunkt.