String en array vergelijken

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

S B

S B

15/04/2018 16:32:45
Quote Anchor link
Ik ben bezig met een script dat een woord vergelijkt met letters die één voor één uit een array worden uitgelezen.
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)
PHP script in nieuw venster Selecteer het PHP script
1
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

?>
Gewijzigd op 15/04/2018 16:33:16 door S B
 
PHP hulp

PHP hulp

24/04/2024 06:39:11
 
Rob Doemaarwat

Rob Doemaarwat

15/04/2018 16:56:33
Quote Anchor link
Huiswerk? Ik zou eerst eens naar in_array() kijken, dat scheelt je een for() loop. En dan eens naar "else" (als in if(...){...}else{...}.
 
Ozzie PHP

Ozzie PHP

15/04/2018 17:02:09
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php

$woord
= 'appel';
$count = strlen($woord);
$array = ['l','b','p','s','p'];
for ($i = 0; $i < $count; $i++) {
    if (!in_array($woord[$i], $array)) $woord = str_replace($woord[$i], '_', $woord);
}

echo $woord;

?>

Voorbeeld: https://3v4l.org/efATj
 
S B

S B

15/04/2018 17:13:49
Quote Anchor link
Ik kende de functie in_array() nog niet, maar bovenstaande voorbeeld is precies wat ik wilde!

Thanks!
 
Rob Doemaarwat

Rob Doemaarwat

15/04/2018 17:36:44
Quote Anchor link
Daar gaan we weer ...
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php

$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 ;-) )
 
Ozzie PHP

Ozzie PHP

15/04/2018 21:16:50
Quote Anchor link
>> (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.
 
Rob Doemaarwat

Rob Doemaarwat

15/04/2018 21:58:38
Quote Anchor link
@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 ;-) ).
 
Ozzie PHP

Ozzie PHP

15/04/2018 22:08:29
Quote Anchor link
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.
 
Thomas van den Heuvel

Thomas van den Heuvel

15/04/2018 22:41:18
Quote Anchor link
Je zou natuurlijk ook kunnen kijken naar verschillende woorden en woorden van verschillende lengte.

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
 
Rob Doemaarwat

Rob Doemaarwat

16/04/2018 07:59:06
Quote Anchor link
@Ozzie: Ik denk dat de regex inderdaad gecached wordt (en evt. nog het aanslingeren van de engine). Als ik de $array elke keer met een random reeks vul, dan kom ik bij 100.000 runs op 1312ms voor de regex, en 310ms voor de in_array (extra tijd ivm het vullen vd $array). Native is dan dus 4x zo snel.

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.
 
Ozzie PHP

Ozzie PHP

16/04/2018 12:05:47
Quote Anchor link
Bij 'normaal' gebruik winnen dus de native PHP-functies. Maar goed ... in de praktijk zal zoiets niet merkbaar zijn. Tenzij je een heeeeeel druk bezochte website hebt en heeeeel veel iteraties zou uitvoeren, dan zou je misschien iets kunnen merken.

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.
 
S B

S B

16/04/2018 14:42:18
Quote Anchor link
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.


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).
 
Thomas van den Heuvel

Thomas van den Heuvel

16/04/2018 16:30:27
Quote Anchor link
Gotcha: strlen() telt ook bytes, en niet per se letters/karakters.

Indien je het volgende $word opslaat in UTF-8 levert dit 6 karakters op:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$word
= 'appël';
echo strlen($word);
?>
 
Ozzie PHP

Ozzie PHP

16/04/2018 21:45:14
Quote Anchor link
>> Gotcha: strlen() telt ook bytes, en niet per se letters/karakters.

"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.
 
Ben van Velzen

Ben van Velzen

16/04/2018 22:34:36
Quote Anchor link
Een gotcha is gewoon iets waar je rekening mee moet houden, heeft niets met wedstrijdjes te maken :)
 
Ozzie PHP

Ozzie PHP

17/04/2018 01:55:43
Quote Anchor link
@Ben: oké ... gotcha ;-)

Gotcha klinkt voor mij als 'ik heb je!'. Maar ja, het zal wel turbotaal zijn, moehahahaaa!
 
Thomas van den Heuvel

Thomas van den Heuvel

17/04/2018 09:30:08
Quote Anchor link
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.
 
Ozzie PHP

Ozzie PHP

17/04/2018 16:14:19
Quote Anchor link
>> Dat is ook niet per se nodig, dit hangt van de character encoding af, en de te verwachten exotische tekens.

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 :-)
 
Rob Doemaarwat

Rob Doemaarwat

17/04/2018 16:27:06
Quote Anchor link
Of toch maar weer die regex :-) (nu met "u" modifier)
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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

?>
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.