Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.php > #12837 > unrolled thread

strpos() before str_replace()? Or, maybe strtr()?

Started byJason C <jwcarlton@gmail.com>
First post2014-02-16 01:49 -0800
Last post2014-02-16 20:49 +0000
Articles 5 on this page of 25 — 9 participants

Back to article view | Back to comp.lang.php


Contents

  strpos() before str_replace()? Or, maybe strtr()? Jason C <jwcarlton@gmail.com> - 2014-02-16 01:49 -0800
    Re: strpos() before str_replace()? Or, maybe strtr()? bill <william@TechServSys.com> - 2014-02-16 07:10 -0500
    Re: strpos() before str_replace()? Or, maybe strtr()? "J.O. Aho" <user@example.net> - 2014-02-16 14:55 +0100
    Re: strpos() before str_replace()? Or, maybe strtr()? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-02-16 15:10 +0100
      Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-16 20:24 +0000
        Re: strpos() before str_replace()? Or, maybe strtr()? "J.O. Aho" <user@example.net> - 2014-02-16 21:41 +0100
          Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-16 20:51 +0000
            Re: strpos() before str_replace()? Or, maybe strtr()? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-02-16 22:16 +0100
              Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-16 23:13 +0000
                Re: strpos() before str_replace()? Or, maybe strtr()? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-02-18 01:33 +0100
            Re: strpos() before str_replace()? Or, maybe strtr()? "J.O. Aho" <user@example.net> - 2014-02-17 06:35 +0100
              Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-17 14:14 +0000
                Re: strpos() before str_replace()? Or, maybe strtr()? "J.O. Aho" <user@example.net> - 2014-02-17 18:55 +0100
              Re: strpos() before str_replace()? Or, maybe strtr()? Christoph Michael Becker <cmbecker69@arcor.de> - 2014-02-17 19:30 +0100
    Re: strpos() before str_replace()? Or, maybe strtr()? Jerry Stuckle <jstucklex@attglobal.net> - 2014-02-16 09:15 -0500
    Re: strpos() before str_replace()? Or, maybe strtr()? Christoph Michael Becker <cmbecker69@arcor.de> - 2014-02-16 15:45 +0100
      Re: strpos() before str_replace()? Or, maybe strtr()? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-02-16 17:23 +0100
        Re: strpos() before str_replace()? Or, maybe strtr()? Christoph Michael Becker <cmbecker69@arcor.de> - 2014-02-16 17:41 +0100
    Re: strpos() before str_replace()? Or, maybe strtr()? Norman Peelman <npeelman@cfl.rr.com> - 2014-02-16 10:08 -0500
      Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-16 19:21 +0000
        Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-16 20:53 +0000
          Re: strpos() before str_replace()? Or, maybe strtr()? Denis McMahon <denismfmcmahon@gmail.com> - 2014-02-17 01:44 +0000
            Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-17 02:19 +0000
        Re: strpos() before str_replace()? Or, maybe strtr()? Norman Peelman <npeelman@cfl.rr.com> - 2014-02-16 18:17 -0500
    Re: strpos() before str_replace()? Or, maybe strtr()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-02-16 20:49 +0000

Page 2 of 2 — ← Prev page 1 [2]


#12851

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2014-02-16 20:53 +0000
Message-ID<0.157e1f73edc557692509.20140216205352GMT.87mwhq6aov.fsf@bsb.me.uk>
In reply to#12846
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Norman Peelman <npeelman@cfl.rr.com> writes:
>
>> On 02/16/2014 04:49 AM, Jason C wrote:
> <snip>
>>> foreach ($userArr as $key => $val) {
>>>    if (strpos($firstname, $key) !== false)
>>>      $firstname = str_replace($key, "****", $firstname);
>>>
>>>    if (strpos($lastname, $key) !== false)
>>>      $lastname = str_replace($key, "****", $lastname);
>>> }
>>
>>
>>   It's slower because you are actually performing the same function
>> twice on each iteration.
>
> Did you try it?  In my tests it's faster (37ms vs 66ms).  This may be
> because of the assignment always being done.

I'm pretty sure that it is simply the overhead of str_replace compared
to that of strpos, and not to do with the assignment.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#12855

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2014-02-17 01:44 +0000
Message-ID<ldrphe$4l4$2@dont-email.me>
In reply to#12851
On Sun, 16 Feb 2014 20:53:52 +0000, Ben Bacarisse wrote:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> 
>> Norman Peelman <npeelman@cfl.rr.com> writes:
>>
>>> On 02/16/2014 04:49 AM, Jason C wrote:
>> <snip>
>>>> foreach ($userArr as $key => $val) {
>>>>    if (strpos($firstname, $key) !== false)
>>>>      $firstname = str_replace($key, "****", $firstname);
>>>>
>>>>    if (strpos($lastname, $key) !== false)
>>>>      $lastname = str_replace($key, "****", $lastname);
>>>> }
>>>
>>>
>>>   It's slower because you are actually performing the same function
>>> twice on each iteration.
>>
>> Did you try it?  In my tests it's faster (37ms vs 66ms).  This may be
>> because of the assignment always being done.
> 
> I'm pretty sure that it is simply the overhead of str_replace compared
> to that of strpos, and not to do with the assignment.
> 
> <snip>

Not sure whether something like this could be faster or not:

  foreach ( $userArr as $key => $val ) {

    if ( ( $f = strpos( $firstname, $key ) ) !== false )
      $firstname = substr( $firstname, 0, $f ) . "****" . 
                   substr( $firstname, $f + strlen( $key ) );

    if ( ( $l = strpos( $lastname, $key ) ) !== false )
      $lastname = substr( $lastname, 0, $l ) . "****" . 
                  substr( $lastname, $l + strlen( $key ) );

  }

As I don't have representative data to test against.

You could use a function:

  function replace_stars( $needle, $pos, $haystack ) {
    return substr( $haystack, 0, $pos ) . "****" . 
           substr( $haystack, $pos + strlen( $needle ) );
  }

  foreach ( $userArr as $key => $val ) {

    if ( ( $f = strpos( $firstname, $key ) ) !== false )
      $firstname = replace_stars( $key, $f, $firstname );

    if ( ( $l = strpos( $lastname, $key ) ) !== false )
      $lastname = replace_stars( $key, $f, $lastname );

  }

but that would be an extra function call, so I inlined the code instead.

p.s. Yes richard, I used an "=" inside an if test, but the difference is 
that I know what I'm doing when I do that, and you don't!

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#12856

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2014-02-17 02:19 +0000
Message-ID<0.36390c759f730e42bbfe.20140217021938GMT.8761oe5vlx.fsf@bsb.me.uk>
In reply to#12855
Denis McMahon <denismfmcmahon@gmail.com> writes:
<snip>
> Not sure whether something like this could be faster or not:
>
>   foreach ( $userArr as $key => $val ) {
>
>     if ( ( $f = strpos( $firstname, $key ) ) !== false )
>       $firstname = substr( $firstname, 0, $f ) . "****" . 
>                    substr( $firstname, $f + strlen( $key ) );
>
>     if ( ( $l = strpos( $lastname, $key ) ) !== false )
>       $lastname = substr( $lastname, 0, $l ) . "****" . 
>                   substr( $lastname, $l + strlen( $key ) );
>
>   }
>
> As I don't have representative data to test against.

Given the structure of the data (lots of tests, with rate matches) I'd
expect this to be much like the strpos + str_replace solution, since the
speed of determining that there is no match dominates.  The assignment
to $l might have a small effect, and that seems to be the case.  The
timings show it's a few percent slower than the plain strpos+str_replace
solution.

The situation is an odd one.  Matches are very rare, and this makes it
worthwhile avoiding as much work as possible when there is no match.
The positions $f and $l are only needed when there is a match, so,
oddly, it makes sense to re-calculate them rather than to assign them
every time.  I.e. this unlikely pattern:

          if (strpos( $firstname, $key) !== false ) {
               $f = strpos($firstname, $key);
               $firstname = substr($firstname, 0, $f) . "****" . 
                                   substr($firstname, $f + strlen($key));
          }

is faster than the above (but by a small, if consistent, amount).
Avoiding 99,999 assignments at the cost of maybe one strpos call is a
win (though I am sure you can construct data sets that reduce or
eliminate this advantage).  When there is no match at all (which the OP
describes as a likely event), avoiding 100,000 assignments at the cost
of nothing, can't be anything but a win!

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#12854

FromNorman Peelman <npeelman@cfl.rr.com>
Date2014-02-16 18:17 -0500
Message-ID<ldrgu9$441$1@dont-email.me>
In reply to#12846
On 02/16/2014 02:21 PM, Ben Bacarisse wrote:
> Norman Peelman <npeelman@cfl.rr.com> writes:
>
>> On 02/16/2014 04:49 AM, Jason C wrote:
> <snip>
>>> foreach ($userArr as $key => $val) {
>>>     if (strpos($firstname, $key) !== false)
>>>       $firstname = str_replace($key, "****", $firstname);
>>>
>>>     if (strpos($lastname, $key) !== false)
>>>       $lastname = str_replace($key, "****", $lastname);
>>> }
>>
>>
>>    It's slower because you are actually performing the same function
>> twice on each iteration.
>
> Did you try it?  In my tests it's faster (37ms vs 66ms).  This may be
> because of the assignment always being done.
>
> I am not saying you could not have got different numbers, just that the
> only way to be sure is to test with the real data in the real
> environment.
>

   Thanks for pointing that out. I didn't think of it that way.



-- 
Norman
Registered Linux user #461062
-Have you been to www.php.net yet?-

[toc] | [prev] | [next] | [standalone]


#12849

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2014-02-16 20:49 +0000
Message-ID<0.5845e901a879f6166491.20140216204914GMT.87y51a6awl.fsf@bsb.me.uk>
In reply to#12837
Jason C <jwcarlton@gmail.com> writes:

> I know that I'm talking about microseconds here, so this is really
> just for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
>   "something" => "anything",
>   ...
> );
>
> foreach ($userArr as $key => $val) {
>   $firstname = str_replace($key, "****", $firstname);
>   $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys, but could
> only potentially contain one key each. It's likely, though, that
> neither will contain any of the keys.
>
> Would it be faster to use strpos() before each str_replace(), like so?:
>
> foreach ($userArr as $key => $val) {
>   if (strpos($firstname, $key) !== false)
>     $firstname = str_replace($key, "****", $firstname);
>
>   if (strpos($lastname, $key) !== false)
>     $lastname = str_replace($key, "****", $lastname);
> }

In a simple test, it seems to be a faster -- significantly faster in
relative terms but not much in absolute time.  The exact numbers depend
on the length of the strings, whether one of the 100,000 strings really
is present or not, the exact keys used and so on, but in all cases that
I tested, checking strpos first pays off.  A typical run: 64ms vs
33ms.

I first thought this might be because of the assignment, but it turns
out not to be.  I think the cause is that str_replace has a high
overhead -- it does more before it ever gets going.  If you can save
this overhead on 99,999 occasions, you save overall despite scanning the
string twice that one time.

Of course, as with all measurements like this, I may not have properly
duplicated your situation, and the result will depend on the machine,
the PHP version, and more besides, so take it with a pinch of salt.
(And note that if the key is numeric, strpos does not do what you
think!)

<snip>
> Or, would strtr() be faster? I've never actually used this function in
> practice; I think it's a slow function, but have never tested it, and
> don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);

In my test, about 89ms -- slower than either of the two above but if
it gives the right result (there is a slight difference in meaning as
pointed out elsethread) I'd probably use it for the clarity it brings.

> Any other suggestions on what might be the fastest option?

If you already have (or could have) the keys and the values in separate
arrays, using the array version of str_replace tested reasonably well
(66ms).  However, as you start off by saying, it's all very marginal.  I
would not normally measure this sort of thing; I'd just write the
simplest code and forget about it.

-- 
Ben.

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.php


csiph-web