05. oktober 2003 - 10:57Der er
31 kommentarer og 2 løsninger
Sammenligne værdier i 2 textareas
Hej
Jeg har brug for et script med to textareas, hvor jeg kan smide nogle mine mailinglister i dem begge og så laver sciptet en samlet mailingliste uden at der er nogle email-adresser, som er gentaget.
OK. Kan jeg antage, at du har dine e-mails adskilt med mellemrum, eller står de på hver sin linie? Vil du ikke helst have den færdige liste skrevet ud i et tekstfelt med en adresse pr. linie?
Her er så en VBscript-løsning. De to maillister findes i tekstområderne text1 og text2 De må gerne begge indeholde gengangere. Når rutinen Flet aktiveres, vil tekstområdet text komme til at indeholde den nye liste. Listen er sorteret.
<script language=VBscript> Option Explicit
sub Sort(A) 'Denne procedure sorterer arrayet 'Det er metoden CombSort, der benyttes. 'Den er næsten lige så hurtig som QuickSort dim n, gap,OK,i,j,tmp 'tabellen A sorteres. CombSort n=Ubound(A) gap = n ok = True While ok If gap < 1 Then gap = 1 ok = (gap <> 1) For i = 0 To n - gap j = i + gap If A(i) > A(j) Then tmp = A(j): A(j) = A(i): A(i) = tmp ok=true End If Next gap = Int(gap / 1.33) Wend end sub
sub Flet dim txt1, txt2,txt, A(1), B, i,n, mail 'Mailadresserne er gemt i de to tekstområder 'text1 og text2 txt1=text1.value: txt2=text2.value txt1=Lcase(Replace(txt1,VBCrLf,",")) txt2=Lcase(Replace(txt2,VBCrLf,",")) A(0)=txt1: A(1)=txt2 txt=join(A,",") B=split(txt,",") sort B n=Ubound(B) mail=B(0) txt=mail for i=1 to n if mail<B(i) then mail=B(i) txt=txt & VBCrLf & mail end if next 'Den nye liste skrives ud i 'tekstområdet text text.value=txt end sub </script>
Hvis man indsætter en email-adresse, som indeholder en bindestreg, så deler scriptet email-adressen over i to dele. (Og det var jo ikke meningen). Kan du ikke lige udbedre dette ?
______________________ <p><b>Email-adresse sortering (gentagelser) </b></p> <script type="text/javascript"> function alleMails(f){
Hvis du tilføjer dette efter <script....script>, får du straks en lille testside. Du skriver dine to lister i de to tekstområder tilvenstre. Når du trykker på knappen, bliver den sammenflettede liste dannet Du behøver ikke at skrive mails. Du kan teste med tal eller bogstaver. Der gøres ikke forskel på små og store. a@b.dk opfattes som samme adresse som A@B.DK
En lille detalje: Jeg har glemt at trimme for blanktegn før og efter. Så for øjeblikket vil ' a@b.c ' og 'a@b.c' opfattes som forskellige. Men det ændres let:
mail=B(0) txt=mail for i=1 to n if mail<B(i) then mail=B(i) txt=txt & VBCrLf & mail end if next
skal ændres til:
mail=trim(B(0)) txt=mail for i=1 to n if mail<trim(B(i)) then mail=trim(B(i)) txt=txt & VBCrLf & mail end if next
sub Sort(A) 'Denne procedure sorterer arrayet 'Det er metoden CombSort, der benyttes. 'Den er næsten lige så hurtig som QuickSort dim n, gap,OK,i,j,tmp 'tabellen A sorteres. CombSort n=Ubound(A) gap = n ok = True While ok If gap < 1 Then gap = 1 ok = (gap <> 1) For i = 0 To n - gap j = i + gap If A(i) > A(j) Then tmp = A(j): A(j) = A(i): A(i) = tmp ok=true End If Next gap = Int(gap / 1.33) Wend end sub
sub Flet dim txt1, txt2,txt, A(1), B, i,n, mail 'Mailadresserne er gemt i de to tekstområder 'text1 og text2 txt=document.form1.text.value: txt1=document.form1.text1.value: txt2=document.form1.text2.value txt1=Lcase(Replace(txt1,VBCrLf,",")) txt2=Lcase(Replace(txt2,VBCrLf,",")) A(0)=txt1: A(1)=txt2 txt=join(A,",") B=split(txt,",") sort B n=Ubound(B) mail=trim(B(0)) txt=mail for i=1 to n if mail<trim(B(i)) then mail=trim(B(i)) txt=txt & VBCrLf & mail end if next 'Den nye liste skrives ud i 'tekstområdet text text.value=txt end sub </script>
Det jeg har lagt op virker skam godt nok, men du har ændret det en smule. Her er det du har lavet med nogle små ændringer: <html> <head> <title></title> </head> <script language=VBscript> Option Explicit
sub Sort(A) 'Denne procedure sorterer arrayet 'Det er metoden CombSort, der benyttes. 'Den er næsten lige så hurtig som QuickSort dim n, gap,OK,i,j,tmp 'tabellen A sorteres. CombSort n=Ubound(A) gap = n ok = True While ok If gap < 1 Then gap = 1 ok = (gap <> 1) For i = 0 To n - gap j = i + gap If A(i) > A(j) Then tmp = A(j): A(j) = A(i): A(i) = tmp ok=true End If Next gap = Int(gap / 1.33) Wend end sub
sub Flet dim txt1, txt2,txt, A(1), B, i,n, mail 'Mailadresserne er gemt i de to tekstområder 'text1 og text2 txt=document.form1.text.value: txt1=document.form1.text1.value: txt2=document.form1.text2.value txt1=Lcase(Replace(txt1,VBCrLf,",")) txt2=Lcase(Replace(txt2,VBCrLf,",")) A(0)=txt1: A(1)=txt2 txt=join(A,",") B=split(txt,",") sort B n=Ubound(B) mail=trim(B(0)) txt=mail for i=1 to n if mail<trim(B(i)) then mail=trim(B(i)) txt=txt & VBCrLf & mail end if next 'Den nye liste skrives ud i 'tekstområdet text document.form1.text.value=txt end sub </script> <body> <form name="form1"> <textarea name="text1" cols=10 rows=20></textarea> <textarea name="text2" cols=10 rows=20></textarea> <textarea name="text" cols=10 rows=20></textarea> <input type=button value="Tryk her" onClick="Flet"> </form> </body>
VBS er håbløst ineffektivt til at behandle arrays - nok det langsomste sprog på markedet til netop den øvelse :) RegExp er jo heller ikke ligefrem det hurtigste, men dog hurtigere.
axkris >> Har du sørget for at validere dine e-mail-adresser ordentligt ved indhøstningen, så vi kan gå udfra, der ikke er dubletter i det enkelte textarea?
olebole>>Det er nok rigtigt, men hvis man griber det rigtigt an går det. Håndtering af tekststrenge er endnu ringere. Alligevel fungerer det jo, hvis man tænker sig om. Og hvad er alternativet? Hvis der er tale om 2 lister med hver 1000 poster, vil roenvings løsning med de to for-løkker give anledning til at "indmaden" bliver udført en million gange, og det vil tage en del længere tid end metoden med arrays og sortering.
Min løsning kan sagtens forbedres en del, hvis der laves fletning af to sorterede lister i stedet for at samle det til en stor liste først. Der er i øvrigt ikke nogen grund til at forudsætte, at de to oprindelige lister er uden dubletter.
Jaja, naturligvis går det ... blot ulideligt langsomt (og man skal jo heller ikke glemme: "At gå ad helvede til" også er en slags "at gå") ;o)
Jeg tror faktisk, du tager fejl. Uden dog at have testet de givne eksempler, formoder jeg roenvings 1.000.000 gennemløb vil afvikle nogenlunde ligeså langsomt, som VBS-skramlet. Anyways ... det kan laves mange hundrede (hvis ikke tusinder) gange hurtigere i JavaScript. Vi skal bare finde ud af, hvad det er, der skal sorteres.
At man ikke behøver forudsætte, de to oprindelige lister ikke indeholder dubletter er måske rigtig nok i VBS-eksemplet ... men hvad er dog det fikse i at bruge et elendigt performende sprog - som tilmed kun virker i en enkelt browser?
Der er masser af gode grunde til at spørge til dubletter, da løsningen jo naturligvis er afhængig heraf ... hvis man altså tænker performance ind i sine løsninger ;o) /mvh
olebole>>Nu har jeg lavet nogle forsøg, hvor jeg har sammenlignet VBscript og JavaScript. Og jeg må konstatere, at det er rent sludder, hvad du lige har sagt mht hastigheder for de to programmeringssprog. Det er muligt du har haft ret med tidligere versioner. Jeg har kørt med IE version 6, nyeste opdatering.
Jeg har først sammenlignet min løsning med roenvings løsning. Her var min løsning 30 gange hurtigere. Jeg brugte som mailadresser to lister med 1000 tilfældige ord.
Jeg har derefter set, hvordan det går, når de to sprog skal håndtere arrays. Jeg så på et array med 100000 elementer, og kørte en for-løkke, hvor elementerne alle fik tildelt værdien "qwertyu". java script: 3 sek VBScript: 0,12 sek Så prøvede jeg med 200000 elementer. java script: 12 sek VBscript: 0,2 sek.
Men nu skal vi nok ikke spame dette spørgsmål mere. Det er dog en diskusion værd. Vi kunne åbne et nyt spørgsmål om dette.
Men det korte af det lange: Du bør ikke udtale dig så kategorisk før du har belæg for det. Dine påstande er simplet hen helt hen i vejret.
JavaScript er født med en sorteringsrutine, som er noget hurtigere end den CombSort, jeg har benyttet. Men det vil alligevel blive dårligere, fordi JavaScript åbenbart ikke er god til at håndtere arrays.
Prøv en tur på nettet - og du vil finde ud af, dine test-værdier har historisk interesse ... du er vist den første, der har gjort de erfaringer.
Jeg udtaler mig absolut ikke med 'påstande', der er helt hen i vejret - og som jeg ikke har belæg for. Jeg har vist netop ry for at udtale på baggrund af viden ... ikke tro og religion :) Jeg er tæt på 100% sikker på, jeg kan finde betydelig større koncensus om min 'påstand', end du kan om:
"Du bør ikke udtale dig så kategorisk før du har belæg for det. Dine påstande er simplet hen helt hen i vejret."
... det er jo helt hen i vejret ;o)
Under alle omstændigheder er denne betydelig mere 'sexy' - formodentlig hurtigere - og så er den ikke skrevet i et proprietært sprog:
<script type="text/JavaScript"> function myTest( f ) { var aMail1, aMail2, tmp, aMail = new Array(); aMail1 = f.bla1.value.split(" "); aMail2 = f.bla2.value.split(" "); aMail1 = aMail1.concat(aMail2); for ( i=0; i<aMail1.length; i++ ) { tmp = aMail1[i]; if ( tmp!="" && !aMail[tmp] ) aMail[tmp] = 1; } // Dette er kun for at teste: for ( key in aMail ) { alert(key); } } </script> <form> <textarea id="bla1">sine@mail.dk mads@mail.dk hugo@mail.dk</textarea> <textarea id="bla2">sine@mail.dk hugo@mail.dk sofie@mail.dk jens@email.dk</textarea> <button onclick="myTest(this.form)">TEST</button> </form>
Dette script skal kun bruges 1 gang pr. måned af mig... det er ikke noget, som skal køres 10.000 gange dagligt, så det er derfor (for mig) ligegyldigt, om det tager 10 eller 20 sekunder eller hvor meget det nu tager :-)
(Vi taler slet ikke om 10 eller 20 sek, vi taler om tiendedele af sekunder, men det er jo noget, der kan bringe sindene i kog, og nogle har åbenbart en stor animositet overfor VBScript)
Hvis man kun ser på hvert enkelt lille job, man har kørende på en maskine - klient eller server - så er det fløjtende ligegyldigt, hvor godt performende ens script er skrevet. Sådan ser virkeligheden dog sjældent ud - og bl.a. derfor er der så mange sites, der kører så forfærdelig dårligt på WWW.
Forskellen på amatør-kodere og professionelle er, at amatøren, der koder et lille site om mors kageopskrifter eller billeder af husets kat, ikke behøver at tænke i performance. Den luksus kan den professionelle til gengæld ikke tillade sig. Han vil have penge for sit arbejde - og så må man også kunne forlange, han gør sit aller yderste for at skrive sin kode, så den performer så godt, som den overhovedet kan.
Et andet fint eksempel er SQL-queries. Hvor ofte ser man ikke selects à la: "SELECT * FROM ..." - hvilket i 9 ud af 10 tilfælde er vildt overkill, da man i de fleste tilfælde kun har brug for enkelte felter. Eller update's uden limit ... komplet tåbeligt i lidt større databaser. I et enkelt kald er forskellen ofte insignifikant, men på en server, der afvikler mange kald i sekundet, kan det _virkelig_ mærkes.
Der er heller ikke noget værre end at ligge på et web-hotel, der kører kanon-langsomt, fordi andre dårligt skrevne sites ligger og sluger al RAM på serveren.
Det pudsige er, at folk straks råber 'religionskrig', når man påpeger det uhensigtsmæssige i at anvende dårligt performende og/eller proprietære sprog/teknologier. I mine øjne ligger fundamentalismen i at insistere på at anvende disse teknologier _på trods_ af deres mange alment kendte og alvorlige mangler :) /mvh
olebole>>Det har nok rigtigt fået dig op på mærkerne det her. Du har da ret i, at man altid skal sørge for at optimere sin kode, der hvor hastighed er vigtig. Men dine betragtninger omkring VBScript er for primitive og fordomsfyldte. Og det er jeg overrasket over, da du ellers virker professionel og dygtig. Du må da indrømme at denne udtalelse fra dig:
"Anyways ... det kan laves mange hundrede (hvis ikke tusinder) gange hurtigere i JavaScript"
er noget sludder. Her har du vist ladet følelserne løbe af med dig.
Dine to løsninger (som jeg synes er gode) er stort set lige hurtige. Hvis jeg prøver at gøre noget tilsvarende i VBScript er de ca. 3 gange hurtigere. I forhold til min oprindelige løsning, hvor der gerne må være dubletter i de oprindelige data, og hvor der sorteres, er de ca. 5 gange hurtigere. I hvert tekstfelt var der 1000 adresser, som alle var forskellige. Tider: dine funktioner: 0,1 sek mine: 0,3 sek (samme metode som du har brugt) 0,5 sek (med sorteringsmetoden)
Jeg har kommenteret i det andet spm, men vil gerne lige kommentere dette også :)
1. Jeg tror vist nok, det er dig, der lader følelserne løbe løbsk :) Hvis du læser, hvad jeg skrev lige det løsrevne citat, så vil du se, jeg _formoder_ VBS-versionen og RegExp-versionen versionen kører lige langsomt - men at jeg under alle omstændigheder kunne skrive den hundreder (om ikke tusinder) gange hurtigere i JavaScript (end den, jeg sammenlignede med på det sted: RegExp-versionen) ... vist ikke helt galt ... eller?
2. Der må være ligeså mange dubletter i mine løsninger, der måtte være - så er du sikker på, det er 'samme metode'? /mvh
1. Jeg tror nu nok, det jeg citerede dig for, kan læses på flere måder, men lad det nu ligge. Det skal ikke ende i pindehuggeri. 2. Dubletter: Det er samme princip [jeg brugte dictionary-objektet i VBscript. Array-håndteringen er jo i den henseende ikke så avanceret som i JavaScript :o)], men som du kan se er JavaScript her bedst med en faktor 3.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.