开发者

Fastest way of deleting a value in a comma separated list

I've got a list of names separated by commas (they may contain other characters), or be empty, but generally looking like this:

NameA,NameB,NameC

I need to create a function to delete a name if开发者_开发百科 its present in the list and which restores the comma separated structure.

eg: if NameA is to be deleted, I should end up with:

NameB,NameC

NOT

,NameB,NameC

Similarly for the rest.

This is what I came up with, is there a better solution?

        $pieces = explode(",", $list);

        $key=array_search($deleteuser, $pieces);
        if(FALSE !== $key)
        {
            unset($pieces[$key]);
        }

        $list = implode(",", $pieces);


That should work pretty well. You may also be interested in PHP's fgetcsv function.
Doc: http://php.net/manual/en/function.fgetcsv.php


You could use the array_splice function to delete from the array. With offset = array_search($deleteuser, $pieces) and length = 1.


If your application data is so large that you are experiencing a crippling amount of lag, then you may have bigger issues that this snippet of code. It might be time to rethink your data storage and processing from the ground up.

In the meantime, here are some benchmarks when imploding a 5001 element array with commas, then using different techniques to remove value 4999. (speeds actually include the generation of the comma-separate string, but all benchmarks are identical in this regard)

  • explode() + array_search() + unset() + implode() (demo)
    System time: ~.009 - .011s

      $pieces = explode(",", $list);
      if (($key = array_search($deleteuser, $pieces)) !== false) {
          unset($pieces[$key]);
      }
      echo implode(",", $pieces);
    

  • explode() + array_search() + array_splice() + implode() (demo)
    System time: ~.010 - .012s

      $pieces = explode(",", $list);
      if (($key = array_search($deleteuser, $pieces)) !== false) {
          array_splice($pieces, $key, 1);
      }
      echo implode(",", $pieces);
    

  • explode() + foreach() + if() + unset() + break + implode() (demo)
    System time: ~.011 - .012s

      $pieces = explode(",", $list);
      foreach ($pieces as $key => $value) {
          if ($value == $deleteuser) {
              unset($pieces[$key]);
              break;
          }
      }
      echo implode(",", $pieces);
    

(note: if you remove the break, the loop can remove multiple occurrences of the needle)


  • explode() + array_diff() + implode() (demo)
    System time: ~.010 - .011s

      $pieces = explode(",", $list);
      $pieces = array_diff($pieces, [$deleteuser]);
      echo implode(",", $pieces);
      // or just: echo implode(',', array_diff(explode(",", $list), [$deleteuser]);
    

  • explode() + array_filter() + implode() (demo)
    System time: ~.010 - .013s

      $pieces = explode(",", $list);
      $pieces = array_filter($pieces, function($v) use ($deleteuser) {
          return $v != $deleteuser;
      });
      echo implode(",", $pieces);
    

  • preg_quote() + preg_replace() (demo) (regex demo)
    System time: ~.007 - .010s

      $needle = preg_quote($deleteuser, '/');
      echo preg_replace('/,' . $needle . '(?=,|$)|^' . $needle . ',/', '', $list);
      // if replacing only one value, declare preg_replace's 4th parameter as 1
    

    Note that if you are using a delimiting character that has a special meaning to the regex engine (like +), then you will need to add a slash before it \+ to escape it and make it literal. This would make the pattern: '/\+' . $needle . '(?=\+|$)|^' . $needle . '\+/'

So while the regex-based snippet proved to be slightly (unnoticeably) faster for my arbitrarily conjured string length, you will need to make your own benchmarks to be sure which is the best performer for your application.

That said, and don't get me wrong I love regex, but the regular expression is going to be the easiest for developers to "get wrong" when it is time to modify the pattern AND I am confident that most devs will agree it has the worst overall comprehensibility.


You could also try a regular expression like this (maybe it can be optimized):

$search = 'NameB';
$list = 'NameA,NameB,NameC';
$list = preg_match('/(^' . $search . ',)|(,' . $search. ')/', '', $list);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜