String en array vergelijken
Nu wil ik echter een "_" (underscore) krijgen op de plaats van de letter van het woord als deze niet in het array voorkomt. Met onderstaande krijg ik "ppl", terwijl ik graag _pp_l zou willen genereren. Iemand een idee hiervoor?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$woord = appel;
$arraytje = array("l","b","p","s","p");
$unieke_array = array_unique($arraytje); // overbodige letters elimineren
for ($m=0 ; $m<strlen($woord) ; $m++) { // ga alle letters van de variabele $woord 1 voor 1 af
for ($n=0 ; $n<count($unieke_array) ; $n++) { // ga alle letters van het array 1 voor 1 af
if ($woord[$m] == $unieke_array[$n]) { // indien letters overeenkomen...
echo $woord[$m];
} // if
} // for1
} // for2
?>
$woord = appel;
$arraytje = array("l","b","p","s","p");
$unieke_array = array_unique($arraytje); // overbodige letters elimineren
for ($m=0 ; $m<strlen($woord) ; $m++) { // ga alle letters van de variabele $woord 1 voor 1 af
for ($n=0 ; $n<count($unieke_array) ; $n++) { // ga alle letters van het array 1 voor 1 af
if ($woord[$m] == $unieke_array[$n]) { // indien letters overeenkomen...
echo $woord[$m];
} // if
} // for1
} // for2
?>
Gewijzigd op 15/04/2018 16:33:16 door S B
Huiswerk? Ik zou eerst eens naar in_array() kijken, dat scheelt je een for() loop. En dan eens naar "else" (als in if(...){...}else{...}.
Thanks!
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$woord = 'appel';
$array = ['l','b','p','s','p'];
print(preg_replace('/[^' . implode($array) . ']/','_',$woord));
?>
$woord = 'appel';
$array = ['l','b','p','s','p'];
print(preg_replace('/[^' . implode($array) . ']/','_',$woord));
?>
Toevoeging op 15/04/2018 17:41:10:
(en nog 2x zo snel ook ;-) )
Nou nee hoor ...
Jouw scriptje kost 131 ms waar mijn scriptje er slechts 71 ms over doet.
Bijna 2x zo traag dus.
@Ozzie: Zijn dat milli of micro seconden? Ik had mijn meting over 100.000x gedaan, en dan zie ik echt die factor 2 (PHP7: 62ms voor de regex, 131ms voor de for/in_array). Als ik het aantal runs terug schroef wordt het verschil inderdaad kleiner, maar niet een factor 2 de ander kant op, hooguit "ongeveer gelijk" (1 run = ongeveer 15 micro sec, maar dan variëren de waarden behoorlijk / niet accuraat meer = reden waarom ik over meerdere runs meet). Zou echter kunnen zijn dat het aanzwengelen van de regex engine initieel een paar micro seconden kost, en dat je dit dus "terug begint te verdienen" bij meerdere runs (gelukkig ben ik verzot op regex-en, dus die engine is meestal al wel wakker ;-) ).
Ms is milliseconde. Ik zie de tijden die ik noemde staan bij die online tester (zie link ergens hierboven). Over het algemeen geldt dat regex functies trager zijn dan native PHP-functies. Dus echt verbazen doet het me niet. Het zou kunnen dat naarmate het aantal runs sneller wordt de regex sneller wordt omdat die wellicht wordt gecachet. Maar dat voordeel zou je dan alleen hebben bij exact dezelfde run. Over het algemeen geldt dat native PHP sneller werkt.
Het stukje code van @Rob is kort, en doet (in 1x) precies wat het zou moeten doen. Uit esthetisch oogpunt (performance be damned) zou ik daar waarschijnlijk ook voor kiezen (maar zorg wel dat je dan ook snapt wat het doet als de leraar om uitleg vraagt :)). De code van @Ozzie doet dingen dubbel indien er dubbele klinkers in zitten omdat je per letter het woord doorloopt.
in_array() is trouwens nogal inefficënt in vergelijking met isset() of array_key_exists(), dus als je je letter-array wat anders opzet kun je al veel winst boeken.
Meten op twee verschillende apparaten is trouwens een beetje appels met peren vergelijken, en tenzij je -zoals @Rob- niet een heleboel iteraties doet kunnen de tijden nogal uiteen lopen.
Gewijzigd op 15/04/2018 22:43:37 door Thomas van den Heuvel
Maarrr ... dat is niet altijd zo. Als ik het $woord 25 karakters of langer maakt "wint" alsnog de regex (random $array, 100.000x). Dito bij slechts 1 of 2 (random) karakters in de $array. De preg_replace() wordt natuurlijk helemaal in C/machine code afgehandeld, en dat heeft dan blijkbaar (soms) toch weer voordelen over "native" PHP code.
Wel leuk dat je in zo'n geval als dit dezelfde functionaliteit op meerdere manieren kunt bereiken. Zo schrijf je waarschijnlijk heel vaak code waarvan je achteraf denkt 'kan dat niet korter of sneller'?
Toen ik begon met programmeren dacht ik dat je een bepaalde functionaliteit maar op 1 manier kon programmeren. Inmiddels besef ik dat dat op tig manieren kan. Een beetje als het schrijven van een boek. Wij kunnen allebei een boek schrijven met als thema dat Jantje vermoord wordt door Pietje. Het eindresultaat zal hetzelfde zijn, maar het verhaal totaal anders. En het ene verhaal zal misschien sneller lezen dan het andere, terwijl het andere juist weer leuker/boeiender is om te lezen. Zo geldt het ook met programmeren. Het is een beetje een kwestie van smaak.
Ozzie PHP op 16/04/2018 12:05:47:
Wel leuk dat je in zo'n geval als dit dezelfde functionaliteit op meerdere manieren kunt bereiken. Zo schrijf je waarschijnlijk heel vaak code waarvan je achteraf denkt 'kan dat niet korter of sneller'?
Toen ik begon met programmeren dacht ik dat je een bepaalde functionaliteit maar op 1 manier kon programmeren. Inmiddels besef ik dat dat op tig manieren kan.
Toen ik begon met programmeren dacht ik dat je een bepaalde functionaliteit maar op 1 manier kon programmeren. Inmiddels besef ik dat dat op tig manieren kan.
Ik ben nog niet zo behendig om het kortste (of snelste) script te schrijven. Gelukkig zijn er mensen zoals jullie die dat sneller kunnen dan ik ;). Grappig dat mijn voorbeeld ook opgelost kan worden zonder for-lus(sen).
Indien je het volgende $word opslaat in UTF-8 levert dit 6 karakters op:
"Gotcha"? Euh ... zijn we een wedstrijdje aan het spelen?
Als je vreemde tekens verwacht, kun je gewoon de multi-byte variant gebruiken.
Dus mb_strlen in plaats van strlen.
Een gotcha is gewoon iets waar je rekening mee moet houden, heeft niets met wedstrijdjes te maken :)
Gotcha klinkt voor mij als 'ik heb je!'. Maar ja, het zal wel turbotaal zijn, moehahahaaa!
Ozzie PHP op 16/04/2018 21:45:14:
Als je vreemde tekens verwacht, kun je gewoon de multi-byte variant gebruiken.
Dat is ook niet per se nodig, dit hangt van de character encoding af, en de te verwachten exotische tekens.
Maar de veronderstelling dat strlen() karakters telt, en niet bytes is een misconceptie. Natuurlijk heeft dit een geschiedenis (gebaseerd op traditionele codepages die vrijwel geen exotische karakters hebben, en waar nagenoeg alles in een byte past), en de naam is niet echt optimaal gekozen / toepasselijk meer. En in veel gevallen zal dit werken, maar lang niet alle. Dit is dus een redelijk standaard instinker, en dit omschrijven als gotcha is vaktaal, geen turbotaal.
Klopt. Dat is wat ik ook bedoel.
Er zijn overigens meer van dit soort mb-varianten, zo heb je ook bijvoorbeeld mb_strpos.
Gotcha ... raar woord voor een instinker, maar ik zal het onthouden :-)
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$woord = 'appël';
$array = ['l','b','p','s','p'];
print(preg_replace('/[^' . implode($array) . ']/u','_',$woord)); //_pp_l
?>
$woord = 'appël';
$array = ['l','b','p','s','p'];
print(preg_replace('/[^' . implode($array) . ']/u','_',$woord)); //_pp_l
?>