stattin skrev:
jo men den array jag ska ha scriptet till har inga nycklar, och det blir väl inte riktigt samma sak ändå, eller?
Näe, det stämmer. Vet inte ens om jag tycker att det är ok att (fel)använda arrayobjektet på det sättet. Det var dumt att ta upp det ö.h.t. Sorry! Strunta i den biten.
stattin skrev:
Ja jag var nog inte ute efter att komprimera ner det så lite som möjligt, tyckte det vart enklare bara att skriva gio() än GetIndexPositions() varje gång man skulle kalla på funktionen.
Ok, jag förstår tänket men håller inte med. Kodar man på det sättet slutar det med namnkonflikter och obegripliga funktioner. Fast det var kanske inte tänkt att vi skulle diskutera olika kodstilar...
Som nitro2k01 skriver syftade jag på att din implementation bryter mot standard då den
- returnerar en array. indexOf() returnerar normalt bara den första positionen. Hittar den inget som matchar parametern får man -1 tillbaka.
- returnerar en sträng. Om det är positionerna man frågar efter är det dem man borde få tillbaka. Positionerna i en array är aldrig en sträng utan heltal.
I efterhand är det tydligare att det inte var meningen att implementera en kopia av indexOf() utan istället en utökad variant som påminner om funktionen. Exemplet du hade med vilseledde mig eftersom det beskrev hur indexOf fungerar och inte hur du vill att ditt skript ska funka. :)
I alla fall...
Det uppdaterade skriptet tycker jag går i helt fel riktning. Jag fattar inte varför det använder sig av en separator ö.h.t. eller varför du håller på och konverterar arrayen till en sträng och sedan kör replace, split osv.
Vi ska inte hålla på och böka med olika datatyper eftersom det bara blir merjobb, ökar risken för feltänk och buggar etc. Vi har en generell datahållare (arrayen) att söka i, that's it.
Vi vill att funktionen ska svara med de positioner som stämmer med sökkriteriat, då tycker jag att den alltid ska returnera en array. Hittas inga element, ja då returnerar man en tom array. Inte false, inte null utan en tom array. Varför? Jo, för det första vet man alltid vad man får tillbaka från funktionen så det blir mycket lättare att använda den. För det andra behöver man inte en massa olika specialfall utan man kan lätt använda arrayen och dess properties (t.ex. length) för att hantera resultatet. Koden blir mycket lättare att förstå om man håller sig till en datatyp.
Nog om det, låt oss gå vidare till lite kodning.
Att IE saknar stöd för Array.indexOf(), det vet vi. Vi vet också att andra webbläsare har stöd för den funktionen och då tycker jag att vi låter dessa webbläsare fortsätta använda sin implementation eftersom den kommer vara snabbare än vår men utöver det är vi nog mer benägna att bygga in buggar. :) Vi lägger funktionaliteten i en sk. wrapper, i denna känner vi av vilken metod vi ska använda: webbläsarens egna eller vår.
Som jag skrev tidigare vill vi kapsla in våra metoder i ett eget scope. JavaScript har inte namespaces ännu (det är inte implementerat än) men man kan fixa samma grej genom att skapa sig en egen klasstruktur. Det finns olika sätt att göra det på men jag har nyligen blivit förtjust i att använda object literal notation som det så fint heter:
var Stattin = {
ArrayUtil : { }
};
Här skapar vi oss en static utilityklass (eller snarare object?) "Stattin" och i det reserverar vi "ArrayUtil", som vi strax skall komplettera med funktionalitet. Först deklarerar vi alltså strukturen, sedan fyller vi på med logik.
var Stattin = {
ArrayUtil : { }
};
Stattin.ArrayUtil.getIndexPositions = function(value, array) {
//här lägger vi vår logik
};
Tidigare skrev jag att man vill låta webbläsare som har en implementering av Array.indexOf() fortsätta använda den så det behöver vi känna av innan vi kodar vidare.
Stattin.ArrayUtil.getIndexPositions = function(value, array) {
if (array.indexOf != undefined) {
return nativeIndexOf(value, array);
} else {
return customIndexOf(value, array);
}
//interna funktioner
function nativeIndexOf(value, array) {
//stöd för Array.indexOf finns redan. Använd det.
}
function customIndexOf(value, array) {
//vår egen logik läggs här
}
};
Nu har vi kommit en bra bit på vägen. Det som fattas är att lägga in själva logiken för hur vi hittar alla positioner. Jag fuskade lite och tog hjälp av Google för att hitta kort och koncis kod för webbläsare som har stöd för Array.indexOf.
Vår egna algoritm gjorde jag så enkel som det bara går. Behöver man optimera gör man det senare, först behöver man en fungerande implementation och lättläslig kod är lättare att finputsa. Eftersom den är så enkel gissar jag att den även är snabbare än att hålla på och joxxa med regex, split, kopiera arrayer osv men det är inte det viktiga i sammanhanget anser jag. Det är fritt fram att såga mina slutsatser om man vill. :)
Stattin.ArrayUtil.getIndexPositions = function(value, array) {
if (array.indexOf != undefined) {
return nativeIndexOf(value, array);
} else {
return customIndexOf(value, array);
}
function nativeIndexOf(value, array) {
var positions = [];
var position = array.indexOf(value);
while (position != -1) {
positions.push(position);
position = array.indexOf(value, position + 1);
}
return positions;
}
function customIndexOf(value, array) {
var positions = [];
for (var i = 0; i < array.length; i++) {
if (value === array[i]) {
positions.push(i);
}
}
return positions;
}
};
Sen så använder man det genom att anropa det:
Stattin.ArrayUtil.getIndexPositions("green", testArray2);
Det här sättet är inte nödvändigtvis det bästa sättet att göra det på men det är en bra grund. Att bygga in nya funktioner är lika enkelt och i.o.m. att vi kapslar in funktionaliteten minskar riskerna för t.ex. namnkollisioner. Namnger man sina filer och klasser på ett smart sätt får man en tydlig kodbas som är lätt att underhålla.
Hoppas att du får ut nåt av allt mitt svammel. :bire