Performance: getting first value from comma delimited string












4












$begingroup$


I've got a string that has values that are delimited by comma's, like so:



$var = '1,23,45,123,145,200';


I'd like to get just the first value, so what I do is create an array from it and get the first element:



$first = current(explode(',', $var));


Fine enough. But this string can sometimes contain perhaps hundreds of values. Exploding it into an array and only using the first one seems kind of a waste. Is there a smarter alternative which is also more performant/less wasteful? I'm thinking some sort of regex or trimming, but I'm guessing that could be actually slower...










share|improve this question









$endgroup$












  • $begingroup$
    +1 for not ignoring your gut feeling, and being reluctant to tackle this using regex. It's proof of sentient activity, some people lack
    $endgroup$
    – Elias Van Ootegem
    Oct 30 '13 at 11:11


















4












$begingroup$


I've got a string that has values that are delimited by comma's, like so:



$var = '1,23,45,123,145,200';


I'd like to get just the first value, so what I do is create an array from it and get the first element:



$first = current(explode(',', $var));


Fine enough. But this string can sometimes contain perhaps hundreds of values. Exploding it into an array and only using the first one seems kind of a waste. Is there a smarter alternative which is also more performant/less wasteful? I'm thinking some sort of regex or trimming, but I'm guessing that could be actually slower...










share|improve this question









$endgroup$












  • $begingroup$
    +1 for not ignoring your gut feeling, and being reluctant to tackle this using regex. It's proof of sentient activity, some people lack
    $endgroup$
    – Elias Van Ootegem
    Oct 30 '13 at 11:11
















4












4








4





$begingroup$


I've got a string that has values that are delimited by comma's, like so:



$var = '1,23,45,123,145,200';


I'd like to get just the first value, so what I do is create an array from it and get the first element:



$first = current(explode(',', $var));


Fine enough. But this string can sometimes contain perhaps hundreds of values. Exploding it into an array and only using the first one seems kind of a waste. Is there a smarter alternative which is also more performant/less wasteful? I'm thinking some sort of regex or trimming, but I'm guessing that could be actually slower...










share|improve this question









$endgroup$




I've got a string that has values that are delimited by comma's, like so:



$var = '1,23,45,123,145,200';


I'd like to get just the first value, so what I do is create an array from it and get the first element:



$first = current(explode(',', $var));


Fine enough. But this string can sometimes contain perhaps hundreds of values. Exploding it into an array and only using the first one seems kind of a waste. Is there a smarter alternative which is also more performant/less wasteful? I'm thinking some sort of regex or trimming, but I'm guessing that could be actually slower...







php performance strings array regex






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Oct 30 '13 at 10:01









kasimirkasimir

17027




17027












  • $begingroup$
    +1 for not ignoring your gut feeling, and being reluctant to tackle this using regex. It's proof of sentient activity, some people lack
    $endgroup$
    – Elias Van Ootegem
    Oct 30 '13 at 11:11




















  • $begingroup$
    +1 for not ignoring your gut feeling, and being reluctant to tackle this using regex. It's proof of sentient activity, some people lack
    $endgroup$
    – Elias Van Ootegem
    Oct 30 '13 at 11:11


















$begingroup$
+1 for not ignoring your gut feeling, and being reluctant to tackle this using regex. It's proof of sentient activity, some people lack
$endgroup$
– Elias Van Ootegem
Oct 30 '13 at 11:11






$begingroup$
+1 for not ignoring your gut feeling, and being reluctant to tackle this using regex. It's proof of sentient activity, some people lack
$endgroup$
– Elias Van Ootegem
Oct 30 '13 at 11:11












4 Answers
4






active

oldest

votes


















7












$begingroup$

UPDATE:

A more complete benchmark script:



$start = $first = $str = null;//create vars, don't benchmark this
//time preg_match
$start = microtime(true);
$first = $str = implode(',', range(213,9999));
if (preg_match('/^[^,]+/', $str, $match))
{
$first = $match[0];
}
echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
//time str* functions
$start = microtime(true);
$first = $str = implode(',', range(213,9999));
$first = substr($str, 0, strpos($str, ','));
echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
//now explode + current
$first = null;
$start = microtime(true);
$str = implode(',', range(213, 9999));
$first = current(explode(',', $str));
echo $first, PHP_EOL, microtime(true) - $start, ' time taken';


The result varried a little, but after 100 runs, the averages amounted to:



#1 substr+strpos: ~.0022ms as 1//base for speed
#2 preg_match: ~.0041 as ~2//about twice as slow as #1
#3 explode: ~.00789 as ~4//about 4 times <=> #1, twice as slow <=> regex




You're absolutely right, exploding a string, constructing an array to get just the first value is a waste of resources, and it is not the fastest way to get what you want.

Some might run to regex for help, and chances are that, in your case that will be faster. But nothing I can think of will beat the speed of PHP's string functions (which are very close to the C string functions). I'd do this:



$first = substr($var, 0, strpos($var, ','));


If the comma isn't present (say $var = '123'), then your current approach will assign 123 to $first. To preserve this behaviour, I'd go for:



$first = strpos($var, ',') === false ? $var : substr($var, 0, strpos($var, ','));


This is to say: if strpos returns false, then there is no comma at all, so assign the entire string to $first, else get everything in front of the first comma.



For completeness sake (and after some initial bench-marking), using preg_match did indeed prove to be faster than using explode with large strings ($var = implode(',', range(1, 9999));), when using this code:



$first = $var = implode(',', range(1,9999));
if (preg_match('/^[^,]*/',$var, $match))
{
$first = $match[0];
}


But honestly, I wouldn't use regex in this case.



In the interest of fairness, and to to clarify how I found the regex to be faster:



$start = microtime(true);
$first = $str = implode(',', range(213,9999));
if (preg_match('/^[^,]+/', $str, $match))
{
$first = $match[0];
}
echo $first, PHP_EOL, $str, PHP_EOL, microtime(true) - $start, ' time taken';
$first = null;
$start = microtime(true);
$str = implode(',', range(213, 9999));
$first = current(explode(',', $str));
echo $first, PHP_EOL, microtime(true) - $start, ' time taken';





share|improve this answer











$endgroup$













  • $begingroup$
    Thanks, I did some benchmarking myself and found that both string and regex solutions are a lot faster than exploding. They are about the same when using this exact code, when losing the ternary notation for the string solution, I found it was actually faster than the regex by about 20% (because ternary uses copy-on-write). So I think I'll use that. As you said: nothing beats the speed of PHP's string functions.
    $endgroup$
    – kasimir
    Oct 30 '13 at 11:01










  • $begingroup$
    @kasimir: I've edited my answer some more, adding my benchmark code, and its results (over 100 runs). I found the string functions to be twice as fast as regex. Though I did run it on a VM, and didn't check how I had configured PHP (it's been ages, and still running 5.3). But if my answer answered your question, would you mind awfully accepting (and or upvoting) it?
    $endgroup$
    – Elias Van Ootegem
    Oct 30 '13 at 11:09












  • $begingroup$
    Don't worry... Ok, so string function is definitely the fastest, great! Also, the regex solution is the 'ugliest' in my opinion, kind of obscuring what you are doing.
    $endgroup$
    – kasimir
    Oct 30 '13 at 13:15








  • 1




    $begingroup$
    Along the same lines: did you know $count = substr_count($var, ',') + 1; is a lot faster than $count = count(explode(',', $var));? codepad.org/KGqtWbxO
    $endgroup$
    – kasimir
    Oct 30 '13 at 13:29










  • $begingroup$
    @Kasimir: It ought to be... I would've been surprized if it wasn't. Iterating through a char comparing j += char[i] == 44 ? 1 : 0 each time just has to be faster than iterating through that string, copying every chunk of data that is not a comma to a new array, only to count the chunks just cannot be as fast, because both operations start by doing the same thing, the difference is the copying, which isn't done in the first case. Good of you to check, though. I'd +1 you again for not taking assumptions for granted, but actually bother checking those things. A commendable attitude
    $endgroup$
    – Elias Van Ootegem
    Oct 30 '13 at 13:59



















2












$begingroup$

I am not familiar with php syntax but I hope you could do this



 $var = "1,23,45,123,145,200";                                                                                                                                                                                                                                                                                                                                                                                                                     
$first_word = substr($var, 0, strpos($var, ','));





share|improve this answer









$endgroup$





















    0












    $begingroup$

    I am shocked that the first three approaches that came to mind didn't even get considered/mentioned/tested!



    In reverse order of my preference...



    Least robust because only works on integers and poorly handles an empty string, casting string as integer: (Demo)



    $tests = ['1,23,45,123,145,200', '345,999,0,1', '0', '0,2', '-1,-122', '', '1.5,2.9'];

    foreach ($tests as $test) {
    var_export((int)$test);
    echo "n";
    }
    // 1
    // 345
    // 0
    // 0
    // -1
    // 0
    // 1


    strstr() with the before_needle parameter: (Demo)



    // same tests
    $before_comma = strstr($test, ',', true);
    var_export($before_comma === false ? $test : $before_comma);
    // '1'
    // '345'
    // '0'
    // '0'
    // '-1'
    // ''
    // '1.5'


    explode() with a limit parameter: (Demo)



    // same tests
    var_export(explode(',', $test, 2)[0]);
    // '1'
    // '345'
    // '0'
    // '0'
    // '-1'
    // ''
    // '1.5'


    While I don't like the idea of creating an array to extract a string value of the first element, it is a single call solution. Setting an element limit means that function isn't asked to do heaps of unnecessary labor.



    I am a big fan of strstr() but it must involve a conditional to properly handle emptying strings.



    If your comma-separated string is never empty and only contains integers, I would strongly recomment the (int) approach, surely that is fastest.



    As much as I love regex, I would not entertain the use of a preg_ call -- not even for a second.





    share









    $endgroup$





















      -1












      $begingroup$

      for me the best way is:



      $str = "Eeny, meeny, miny, moe";
      $first = explode(',', $str)[0];





      share|improve this answer









      $endgroup$









      • 1




        $begingroup$
        Great! But that's not a review. Reviews contain at least one insightful remark about the code provided. Why is your code better than the code provided? What problems does the original code have that yours does not?
        $endgroup$
        – Mast
        May 23 '18 at 18:16










      • $begingroup$
        This is pretty much exactly the same as the solution I did not want to use and my question was all about...
        $endgroup$
        – kasimir
        May 24 '18 at 15:42











      Your Answer





      StackExchange.ifUsing("editor", function () {
      return StackExchange.using("mathjaxEditing", function () {
      StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
      StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
      });
      });
      }, "mathjax-editing");

      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "196"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f33500%2fperformance-getting-first-value-from-comma-delimited-string%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      7












      $begingroup$

      UPDATE:

      A more complete benchmark script:



      $start = $first = $str = null;//create vars, don't benchmark this
      //time preg_match
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //time str* functions
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      $first = substr($str, 0, strpos($str, ','));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //now explode + current
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';


      The result varried a little, but after 100 runs, the averages amounted to:



      #1 substr+strpos: ~.0022ms as 1//base for speed
      #2 preg_match: ~.0041 as ~2//about twice as slow as #1
      #3 explode: ~.00789 as ~4//about 4 times <=> #1, twice as slow <=> regex




      You're absolutely right, exploding a string, constructing an array to get just the first value is a waste of resources, and it is not the fastest way to get what you want.

      Some might run to regex for help, and chances are that, in your case that will be faster. But nothing I can think of will beat the speed of PHP's string functions (which are very close to the C string functions). I'd do this:



      $first = substr($var, 0, strpos($var, ','));


      If the comma isn't present (say $var = '123'), then your current approach will assign 123 to $first. To preserve this behaviour, I'd go for:



      $first = strpos($var, ',') === false ? $var : substr($var, 0, strpos($var, ','));


      This is to say: if strpos returns false, then there is no comma at all, so assign the entire string to $first, else get everything in front of the first comma.



      For completeness sake (and after some initial bench-marking), using preg_match did indeed prove to be faster than using explode with large strings ($var = implode(',', range(1, 9999));), when using this code:



      $first = $var = implode(',', range(1,9999));
      if (preg_match('/^[^,]*/',$var, $match))
      {
      $first = $match[0];
      }


      But honestly, I wouldn't use regex in this case.



      In the interest of fairness, and to to clarify how I found the regex to be faster:



      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, $str, PHP_EOL, microtime(true) - $start, ' time taken';
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';





      share|improve this answer











      $endgroup$













      • $begingroup$
        Thanks, I did some benchmarking myself and found that both string and regex solutions are a lot faster than exploding. They are about the same when using this exact code, when losing the ternary notation for the string solution, I found it was actually faster than the regex by about 20% (because ternary uses copy-on-write). So I think I'll use that. As you said: nothing beats the speed of PHP's string functions.
        $endgroup$
        – kasimir
        Oct 30 '13 at 11:01










      • $begingroup$
        @kasimir: I've edited my answer some more, adding my benchmark code, and its results (over 100 runs). I found the string functions to be twice as fast as regex. Though I did run it on a VM, and didn't check how I had configured PHP (it's been ages, and still running 5.3). But if my answer answered your question, would you mind awfully accepting (and or upvoting) it?
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 11:09












      • $begingroup$
        Don't worry... Ok, so string function is definitely the fastest, great! Also, the regex solution is the 'ugliest' in my opinion, kind of obscuring what you are doing.
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:15








      • 1




        $begingroup$
        Along the same lines: did you know $count = substr_count($var, ',') + 1; is a lot faster than $count = count(explode(',', $var));? codepad.org/KGqtWbxO
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:29










      • $begingroup$
        @Kasimir: It ought to be... I would've been surprized if it wasn't. Iterating through a char comparing j += char[i] == 44 ? 1 : 0 each time just has to be faster than iterating through that string, copying every chunk of data that is not a comma to a new array, only to count the chunks just cannot be as fast, because both operations start by doing the same thing, the difference is the copying, which isn't done in the first case. Good of you to check, though. I'd +1 you again for not taking assumptions for granted, but actually bother checking those things. A commendable attitude
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 13:59
















      7












      $begingroup$

      UPDATE:

      A more complete benchmark script:



      $start = $first = $str = null;//create vars, don't benchmark this
      //time preg_match
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //time str* functions
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      $first = substr($str, 0, strpos($str, ','));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //now explode + current
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';


      The result varried a little, but after 100 runs, the averages amounted to:



      #1 substr+strpos: ~.0022ms as 1//base for speed
      #2 preg_match: ~.0041 as ~2//about twice as slow as #1
      #3 explode: ~.00789 as ~4//about 4 times <=> #1, twice as slow <=> regex




      You're absolutely right, exploding a string, constructing an array to get just the first value is a waste of resources, and it is not the fastest way to get what you want.

      Some might run to regex for help, and chances are that, in your case that will be faster. But nothing I can think of will beat the speed of PHP's string functions (which are very close to the C string functions). I'd do this:



      $first = substr($var, 0, strpos($var, ','));


      If the comma isn't present (say $var = '123'), then your current approach will assign 123 to $first. To preserve this behaviour, I'd go for:



      $first = strpos($var, ',') === false ? $var : substr($var, 0, strpos($var, ','));


      This is to say: if strpos returns false, then there is no comma at all, so assign the entire string to $first, else get everything in front of the first comma.



      For completeness sake (and after some initial bench-marking), using preg_match did indeed prove to be faster than using explode with large strings ($var = implode(',', range(1, 9999));), when using this code:



      $first = $var = implode(',', range(1,9999));
      if (preg_match('/^[^,]*/',$var, $match))
      {
      $first = $match[0];
      }


      But honestly, I wouldn't use regex in this case.



      In the interest of fairness, and to to clarify how I found the regex to be faster:



      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, $str, PHP_EOL, microtime(true) - $start, ' time taken';
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';





      share|improve this answer











      $endgroup$













      • $begingroup$
        Thanks, I did some benchmarking myself and found that both string and regex solutions are a lot faster than exploding. They are about the same when using this exact code, when losing the ternary notation for the string solution, I found it was actually faster than the regex by about 20% (because ternary uses copy-on-write). So I think I'll use that. As you said: nothing beats the speed of PHP's string functions.
        $endgroup$
        – kasimir
        Oct 30 '13 at 11:01










      • $begingroup$
        @kasimir: I've edited my answer some more, adding my benchmark code, and its results (over 100 runs). I found the string functions to be twice as fast as regex. Though I did run it on a VM, and didn't check how I had configured PHP (it's been ages, and still running 5.3). But if my answer answered your question, would you mind awfully accepting (and or upvoting) it?
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 11:09












      • $begingroup$
        Don't worry... Ok, so string function is definitely the fastest, great! Also, the regex solution is the 'ugliest' in my opinion, kind of obscuring what you are doing.
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:15








      • 1




        $begingroup$
        Along the same lines: did you know $count = substr_count($var, ',') + 1; is a lot faster than $count = count(explode(',', $var));? codepad.org/KGqtWbxO
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:29










      • $begingroup$
        @Kasimir: It ought to be... I would've been surprized if it wasn't. Iterating through a char comparing j += char[i] == 44 ? 1 : 0 each time just has to be faster than iterating through that string, copying every chunk of data that is not a comma to a new array, only to count the chunks just cannot be as fast, because both operations start by doing the same thing, the difference is the copying, which isn't done in the first case. Good of you to check, though. I'd +1 you again for not taking assumptions for granted, but actually bother checking those things. A commendable attitude
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 13:59














      7












      7








      7





      $begingroup$

      UPDATE:

      A more complete benchmark script:



      $start = $first = $str = null;//create vars, don't benchmark this
      //time preg_match
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //time str* functions
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      $first = substr($str, 0, strpos($str, ','));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //now explode + current
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';


      The result varried a little, but after 100 runs, the averages amounted to:



      #1 substr+strpos: ~.0022ms as 1//base for speed
      #2 preg_match: ~.0041 as ~2//about twice as slow as #1
      #3 explode: ~.00789 as ~4//about 4 times <=> #1, twice as slow <=> regex




      You're absolutely right, exploding a string, constructing an array to get just the first value is a waste of resources, and it is not the fastest way to get what you want.

      Some might run to regex for help, and chances are that, in your case that will be faster. But nothing I can think of will beat the speed of PHP's string functions (which are very close to the C string functions). I'd do this:



      $first = substr($var, 0, strpos($var, ','));


      If the comma isn't present (say $var = '123'), then your current approach will assign 123 to $first. To preserve this behaviour, I'd go for:



      $first = strpos($var, ',') === false ? $var : substr($var, 0, strpos($var, ','));


      This is to say: if strpos returns false, then there is no comma at all, so assign the entire string to $first, else get everything in front of the first comma.



      For completeness sake (and after some initial bench-marking), using preg_match did indeed prove to be faster than using explode with large strings ($var = implode(',', range(1, 9999));), when using this code:



      $first = $var = implode(',', range(1,9999));
      if (preg_match('/^[^,]*/',$var, $match))
      {
      $first = $match[0];
      }


      But honestly, I wouldn't use regex in this case.



      In the interest of fairness, and to to clarify how I found the regex to be faster:



      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, $str, PHP_EOL, microtime(true) - $start, ' time taken';
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';





      share|improve this answer











      $endgroup$



      UPDATE:

      A more complete benchmark script:



      $start = $first = $str = null;//create vars, don't benchmark this
      //time preg_match
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //time str* functions
      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      $first = substr($str, 0, strpos($str, ','));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken<br/>', PHP_EOL;
      //now explode + current
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';


      The result varried a little, but after 100 runs, the averages amounted to:



      #1 substr+strpos: ~.0022ms as 1//base for speed
      #2 preg_match: ~.0041 as ~2//about twice as slow as #1
      #3 explode: ~.00789 as ~4//about 4 times <=> #1, twice as slow <=> regex




      You're absolutely right, exploding a string, constructing an array to get just the first value is a waste of resources, and it is not the fastest way to get what you want.

      Some might run to regex for help, and chances are that, in your case that will be faster. But nothing I can think of will beat the speed of PHP's string functions (which are very close to the C string functions). I'd do this:



      $first = substr($var, 0, strpos($var, ','));


      If the comma isn't present (say $var = '123'), then your current approach will assign 123 to $first. To preserve this behaviour, I'd go for:



      $first = strpos($var, ',') === false ? $var : substr($var, 0, strpos($var, ','));


      This is to say: if strpos returns false, then there is no comma at all, so assign the entire string to $first, else get everything in front of the first comma.



      For completeness sake (and after some initial bench-marking), using preg_match did indeed prove to be faster than using explode with large strings ($var = implode(',', range(1, 9999));), when using this code:



      $first = $var = implode(',', range(1,9999));
      if (preg_match('/^[^,]*/',$var, $match))
      {
      $first = $match[0];
      }


      But honestly, I wouldn't use regex in this case.



      In the interest of fairness, and to to clarify how I found the regex to be faster:



      $start = microtime(true);
      $first = $str = implode(',', range(213,9999));
      if (preg_match('/^[^,]+/', $str, $match))
      {
      $first = $match[0];
      }
      echo $first, PHP_EOL, $str, PHP_EOL, microtime(true) - $start, ' time taken';
      $first = null;
      $start = microtime(true);
      $str = implode(',', range(213, 9999));
      $first = current(explode(',', $str));
      echo $first, PHP_EOL, microtime(true) - $start, ' time taken';






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Oct 30 '13 at 11:05

























      answered Oct 30 '13 at 10:35









      Elias Van OotegemElias Van Ootegem

      9,0332144




      9,0332144












      • $begingroup$
        Thanks, I did some benchmarking myself and found that both string and regex solutions are a lot faster than exploding. They are about the same when using this exact code, when losing the ternary notation for the string solution, I found it was actually faster than the regex by about 20% (because ternary uses copy-on-write). So I think I'll use that. As you said: nothing beats the speed of PHP's string functions.
        $endgroup$
        – kasimir
        Oct 30 '13 at 11:01










      • $begingroup$
        @kasimir: I've edited my answer some more, adding my benchmark code, and its results (over 100 runs). I found the string functions to be twice as fast as regex. Though I did run it on a VM, and didn't check how I had configured PHP (it's been ages, and still running 5.3). But if my answer answered your question, would you mind awfully accepting (and or upvoting) it?
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 11:09












      • $begingroup$
        Don't worry... Ok, so string function is definitely the fastest, great! Also, the regex solution is the 'ugliest' in my opinion, kind of obscuring what you are doing.
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:15








      • 1




        $begingroup$
        Along the same lines: did you know $count = substr_count($var, ',') + 1; is a lot faster than $count = count(explode(',', $var));? codepad.org/KGqtWbxO
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:29










      • $begingroup$
        @Kasimir: It ought to be... I would've been surprized if it wasn't. Iterating through a char comparing j += char[i] == 44 ? 1 : 0 each time just has to be faster than iterating through that string, copying every chunk of data that is not a comma to a new array, only to count the chunks just cannot be as fast, because both operations start by doing the same thing, the difference is the copying, which isn't done in the first case. Good of you to check, though. I'd +1 you again for not taking assumptions for granted, but actually bother checking those things. A commendable attitude
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 13:59


















      • $begingroup$
        Thanks, I did some benchmarking myself and found that both string and regex solutions are a lot faster than exploding. They are about the same when using this exact code, when losing the ternary notation for the string solution, I found it was actually faster than the regex by about 20% (because ternary uses copy-on-write). So I think I'll use that. As you said: nothing beats the speed of PHP's string functions.
        $endgroup$
        – kasimir
        Oct 30 '13 at 11:01










      • $begingroup$
        @kasimir: I've edited my answer some more, adding my benchmark code, and its results (over 100 runs). I found the string functions to be twice as fast as regex. Though I did run it on a VM, and didn't check how I had configured PHP (it's been ages, and still running 5.3). But if my answer answered your question, would you mind awfully accepting (and or upvoting) it?
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 11:09












      • $begingroup$
        Don't worry... Ok, so string function is definitely the fastest, great! Also, the regex solution is the 'ugliest' in my opinion, kind of obscuring what you are doing.
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:15








      • 1




        $begingroup$
        Along the same lines: did you know $count = substr_count($var, ',') + 1; is a lot faster than $count = count(explode(',', $var));? codepad.org/KGqtWbxO
        $endgroup$
        – kasimir
        Oct 30 '13 at 13:29










      • $begingroup$
        @Kasimir: It ought to be... I would've been surprized if it wasn't. Iterating through a char comparing j += char[i] == 44 ? 1 : 0 each time just has to be faster than iterating through that string, copying every chunk of data that is not a comma to a new array, only to count the chunks just cannot be as fast, because both operations start by doing the same thing, the difference is the copying, which isn't done in the first case. Good of you to check, though. I'd +1 you again for not taking assumptions for granted, but actually bother checking those things. A commendable attitude
        $endgroup$
        – Elias Van Ootegem
        Oct 30 '13 at 13:59
















      $begingroup$
      Thanks, I did some benchmarking myself and found that both string and regex solutions are a lot faster than exploding. They are about the same when using this exact code, when losing the ternary notation for the string solution, I found it was actually faster than the regex by about 20% (because ternary uses copy-on-write). So I think I'll use that. As you said: nothing beats the speed of PHP's string functions.
      $endgroup$
      – kasimir
      Oct 30 '13 at 11:01




      $begingroup$
      Thanks, I did some benchmarking myself and found that both string and regex solutions are a lot faster than exploding. They are about the same when using this exact code, when losing the ternary notation for the string solution, I found it was actually faster than the regex by about 20% (because ternary uses copy-on-write). So I think I'll use that. As you said: nothing beats the speed of PHP's string functions.
      $endgroup$
      – kasimir
      Oct 30 '13 at 11:01












      $begingroup$
      @kasimir: I've edited my answer some more, adding my benchmark code, and its results (over 100 runs). I found the string functions to be twice as fast as regex. Though I did run it on a VM, and didn't check how I had configured PHP (it's been ages, and still running 5.3). But if my answer answered your question, would you mind awfully accepting (and or upvoting) it?
      $endgroup$
      – Elias Van Ootegem
      Oct 30 '13 at 11:09






      $begingroup$
      @kasimir: I've edited my answer some more, adding my benchmark code, and its results (over 100 runs). I found the string functions to be twice as fast as regex. Though I did run it on a VM, and didn't check how I had configured PHP (it's been ages, and still running 5.3). But if my answer answered your question, would you mind awfully accepting (and or upvoting) it?
      $endgroup$
      – Elias Van Ootegem
      Oct 30 '13 at 11:09














      $begingroup$
      Don't worry... Ok, so string function is definitely the fastest, great! Also, the regex solution is the 'ugliest' in my opinion, kind of obscuring what you are doing.
      $endgroup$
      – kasimir
      Oct 30 '13 at 13:15






      $begingroup$
      Don't worry... Ok, so string function is definitely the fastest, great! Also, the regex solution is the 'ugliest' in my opinion, kind of obscuring what you are doing.
      $endgroup$
      – kasimir
      Oct 30 '13 at 13:15






      1




      1




      $begingroup$
      Along the same lines: did you know $count = substr_count($var, ',') + 1; is a lot faster than $count = count(explode(',', $var));? codepad.org/KGqtWbxO
      $endgroup$
      – kasimir
      Oct 30 '13 at 13:29




      $begingroup$
      Along the same lines: did you know $count = substr_count($var, ',') + 1; is a lot faster than $count = count(explode(',', $var));? codepad.org/KGqtWbxO
      $endgroup$
      – kasimir
      Oct 30 '13 at 13:29












      $begingroup$
      @Kasimir: It ought to be... I would've been surprized if it wasn't. Iterating through a char comparing j += char[i] == 44 ? 1 : 0 each time just has to be faster than iterating through that string, copying every chunk of data that is not a comma to a new array, only to count the chunks just cannot be as fast, because both operations start by doing the same thing, the difference is the copying, which isn't done in the first case. Good of you to check, though. I'd +1 you again for not taking assumptions for granted, but actually bother checking those things. A commendable attitude
      $endgroup$
      – Elias Van Ootegem
      Oct 30 '13 at 13:59




      $begingroup$
      @Kasimir: It ought to be... I would've been surprized if it wasn't. Iterating through a char comparing j += char[i] == 44 ? 1 : 0 each time just has to be faster than iterating through that string, copying every chunk of data that is not a comma to a new array, only to count the chunks just cannot be as fast, because both operations start by doing the same thing, the difference is the copying, which isn't done in the first case. Good of you to check, though. I'd +1 you again for not taking assumptions for granted, but actually bother checking those things. A commendable attitude
      $endgroup$
      – Elias Van Ootegem
      Oct 30 '13 at 13:59













      2












      $begingroup$

      I am not familiar with php syntax but I hope you could do this



       $var = "1,23,45,123,145,200";                                                                                                                                                                                                                                                                                                                                                                                                                     
      $first_word = substr($var, 0, strpos($var, ','));





      share|improve this answer









      $endgroup$


















        2












        $begingroup$

        I am not familiar with php syntax but I hope you could do this



         $var = "1,23,45,123,145,200";                                                                                                                                                                                                                                                                                                                                                                                                                     
        $first_word = substr($var, 0, strpos($var, ','));





        share|improve this answer









        $endgroup$
















          2












          2








          2





          $begingroup$

          I am not familiar with php syntax but I hope you could do this



           $var = "1,23,45,123,145,200";                                                                                                                                                                                                                                                                                                                                                                                                                     
          $first_word = substr($var, 0, strpos($var, ','));





          share|improve this answer









          $endgroup$



          I am not familiar with php syntax but I hope you could do this



           $var = "1,23,45,123,145,200";                                                                                                                                                                                                                                                                                                                                                                                                                     
          $first_word = substr($var, 0, strpos($var, ','));






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 30 '13 at 10:33









          KinjalKinjal

          97021023




          97021023























              0












              $begingroup$

              I am shocked that the first three approaches that came to mind didn't even get considered/mentioned/tested!



              In reverse order of my preference...



              Least robust because only works on integers and poorly handles an empty string, casting string as integer: (Demo)



              $tests = ['1,23,45,123,145,200', '345,999,0,1', '0', '0,2', '-1,-122', '', '1.5,2.9'];

              foreach ($tests as $test) {
              var_export((int)$test);
              echo "n";
              }
              // 1
              // 345
              // 0
              // 0
              // -1
              // 0
              // 1


              strstr() with the before_needle parameter: (Demo)



              // same tests
              $before_comma = strstr($test, ',', true);
              var_export($before_comma === false ? $test : $before_comma);
              // '1'
              // '345'
              // '0'
              // '0'
              // '-1'
              // ''
              // '1.5'


              explode() with a limit parameter: (Demo)



              // same tests
              var_export(explode(',', $test, 2)[0]);
              // '1'
              // '345'
              // '0'
              // '0'
              // '-1'
              // ''
              // '1.5'


              While I don't like the idea of creating an array to extract a string value of the first element, it is a single call solution. Setting an element limit means that function isn't asked to do heaps of unnecessary labor.



              I am a big fan of strstr() but it must involve a conditional to properly handle emptying strings.



              If your comma-separated string is never empty and only contains integers, I would strongly recomment the (int) approach, surely that is fastest.



              As much as I love regex, I would not entertain the use of a preg_ call -- not even for a second.





              share









              $endgroup$


















                0












                $begingroup$

                I am shocked that the first three approaches that came to mind didn't even get considered/mentioned/tested!



                In reverse order of my preference...



                Least robust because only works on integers and poorly handles an empty string, casting string as integer: (Demo)



                $tests = ['1,23,45,123,145,200', '345,999,0,1', '0', '0,2', '-1,-122', '', '1.5,2.9'];

                foreach ($tests as $test) {
                var_export((int)$test);
                echo "n";
                }
                // 1
                // 345
                // 0
                // 0
                // -1
                // 0
                // 1


                strstr() with the before_needle parameter: (Demo)



                // same tests
                $before_comma = strstr($test, ',', true);
                var_export($before_comma === false ? $test : $before_comma);
                // '1'
                // '345'
                // '0'
                // '0'
                // '-1'
                // ''
                // '1.5'


                explode() with a limit parameter: (Demo)



                // same tests
                var_export(explode(',', $test, 2)[0]);
                // '1'
                // '345'
                // '0'
                // '0'
                // '-1'
                // ''
                // '1.5'


                While I don't like the idea of creating an array to extract a string value of the first element, it is a single call solution. Setting an element limit means that function isn't asked to do heaps of unnecessary labor.



                I am a big fan of strstr() but it must involve a conditional to properly handle emptying strings.



                If your comma-separated string is never empty and only contains integers, I would strongly recomment the (int) approach, surely that is fastest.



                As much as I love regex, I would not entertain the use of a preg_ call -- not even for a second.





                share









                $endgroup$
















                  0












                  0








                  0





                  $begingroup$

                  I am shocked that the first three approaches that came to mind didn't even get considered/mentioned/tested!



                  In reverse order of my preference...



                  Least robust because only works on integers and poorly handles an empty string, casting string as integer: (Demo)



                  $tests = ['1,23,45,123,145,200', '345,999,0,1', '0', '0,2', '-1,-122', '', '1.5,2.9'];

                  foreach ($tests as $test) {
                  var_export((int)$test);
                  echo "n";
                  }
                  // 1
                  // 345
                  // 0
                  // 0
                  // -1
                  // 0
                  // 1


                  strstr() with the before_needle parameter: (Demo)



                  // same tests
                  $before_comma = strstr($test, ',', true);
                  var_export($before_comma === false ? $test : $before_comma);
                  // '1'
                  // '345'
                  // '0'
                  // '0'
                  // '-1'
                  // ''
                  // '1.5'


                  explode() with a limit parameter: (Demo)



                  // same tests
                  var_export(explode(',', $test, 2)[0]);
                  // '1'
                  // '345'
                  // '0'
                  // '0'
                  // '-1'
                  // ''
                  // '1.5'


                  While I don't like the idea of creating an array to extract a string value of the first element, it is a single call solution. Setting an element limit means that function isn't asked to do heaps of unnecessary labor.



                  I am a big fan of strstr() but it must involve a conditional to properly handle emptying strings.



                  If your comma-separated string is never empty and only contains integers, I would strongly recomment the (int) approach, surely that is fastest.



                  As much as I love regex, I would not entertain the use of a preg_ call -- not even for a second.





                  share









                  $endgroup$



                  I am shocked that the first three approaches that came to mind didn't even get considered/mentioned/tested!



                  In reverse order of my preference...



                  Least robust because only works on integers and poorly handles an empty string, casting string as integer: (Demo)



                  $tests = ['1,23,45,123,145,200', '345,999,0,1', '0', '0,2', '-1,-122', '', '1.5,2.9'];

                  foreach ($tests as $test) {
                  var_export((int)$test);
                  echo "n";
                  }
                  // 1
                  // 345
                  // 0
                  // 0
                  // -1
                  // 0
                  // 1


                  strstr() with the before_needle parameter: (Demo)



                  // same tests
                  $before_comma = strstr($test, ',', true);
                  var_export($before_comma === false ? $test : $before_comma);
                  // '1'
                  // '345'
                  // '0'
                  // '0'
                  // '-1'
                  // ''
                  // '1.5'


                  explode() with a limit parameter: (Demo)



                  // same tests
                  var_export(explode(',', $test, 2)[0]);
                  // '1'
                  // '345'
                  // '0'
                  // '0'
                  // '-1'
                  // ''
                  // '1.5'


                  While I don't like the idea of creating an array to extract a string value of the first element, it is a single call solution. Setting an element limit means that function isn't asked to do heaps of unnecessary labor.



                  I am a big fan of strstr() but it must involve a conditional to properly handle emptying strings.



                  If your comma-separated string is never empty and only contains integers, I would strongly recomment the (int) approach, surely that is fastest.



                  As much as I love regex, I would not entertain the use of a preg_ call -- not even for a second.






                  share











                  share


                  share










                  answered 6 mins ago









                  mickmackusamickmackusa

                  1,149213




                  1,149213























                      -1












                      $begingroup$

                      for me the best way is:



                      $str = "Eeny, meeny, miny, moe";
                      $first = explode(',', $str)[0];





                      share|improve this answer









                      $endgroup$









                      • 1




                        $begingroup$
                        Great! But that's not a review. Reviews contain at least one insightful remark about the code provided. Why is your code better than the code provided? What problems does the original code have that yours does not?
                        $endgroup$
                        – Mast
                        May 23 '18 at 18:16










                      • $begingroup$
                        This is pretty much exactly the same as the solution I did not want to use and my question was all about...
                        $endgroup$
                        – kasimir
                        May 24 '18 at 15:42
















                      -1












                      $begingroup$

                      for me the best way is:



                      $str = "Eeny, meeny, miny, moe";
                      $first = explode(',', $str)[0];





                      share|improve this answer









                      $endgroup$









                      • 1




                        $begingroup$
                        Great! But that's not a review. Reviews contain at least one insightful remark about the code provided. Why is your code better than the code provided? What problems does the original code have that yours does not?
                        $endgroup$
                        – Mast
                        May 23 '18 at 18:16










                      • $begingroup$
                        This is pretty much exactly the same as the solution I did not want to use and my question was all about...
                        $endgroup$
                        – kasimir
                        May 24 '18 at 15:42














                      -1












                      -1








                      -1





                      $begingroup$

                      for me the best way is:



                      $str = "Eeny, meeny, miny, moe";
                      $first = explode(',', $str)[0];





                      share|improve this answer









                      $endgroup$



                      for me the best way is:



                      $str = "Eeny, meeny, miny, moe";
                      $first = explode(',', $str)[0];






                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered May 23 '18 at 18:10









                      Sal CelliSal Celli

                      99




                      99








                      • 1




                        $begingroup$
                        Great! But that's not a review. Reviews contain at least one insightful remark about the code provided. Why is your code better than the code provided? What problems does the original code have that yours does not?
                        $endgroup$
                        – Mast
                        May 23 '18 at 18:16










                      • $begingroup$
                        This is pretty much exactly the same as the solution I did not want to use and my question was all about...
                        $endgroup$
                        – kasimir
                        May 24 '18 at 15:42














                      • 1




                        $begingroup$
                        Great! But that's not a review. Reviews contain at least one insightful remark about the code provided. Why is your code better than the code provided? What problems does the original code have that yours does not?
                        $endgroup$
                        – Mast
                        May 23 '18 at 18:16










                      • $begingroup$
                        This is pretty much exactly the same as the solution I did not want to use and my question was all about...
                        $endgroup$
                        – kasimir
                        May 24 '18 at 15:42








                      1




                      1




                      $begingroup$
                      Great! But that's not a review. Reviews contain at least one insightful remark about the code provided. Why is your code better than the code provided? What problems does the original code have that yours does not?
                      $endgroup$
                      – Mast
                      May 23 '18 at 18:16




                      $begingroup$
                      Great! But that's not a review. Reviews contain at least one insightful remark about the code provided. Why is your code better than the code provided? What problems does the original code have that yours does not?
                      $endgroup$
                      – Mast
                      May 23 '18 at 18:16












                      $begingroup$
                      This is pretty much exactly the same as the solution I did not want to use and my question was all about...
                      $endgroup$
                      – kasimir
                      May 24 '18 at 15:42




                      $begingroup$
                      This is pretty much exactly the same as the solution I did not want to use and my question was all about...
                      $endgroup$
                      – kasimir
                      May 24 '18 at 15:42


















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Code Review Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f33500%2fperformance-getting-first-value-from-comma-delimited-string%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      How to make a Squid Proxy server?

                      Is this a new Fibonacci Identity?

                      19世紀