PHP gets the position of every first character in a string into an array

For a string, for example:

$string = " this is a string "; 

What is the best approach for returning a csv array containing one number for each word that represents its first character position as follows:

 $string = " this is a string "; ^ ^ ^ ^ 2 11 16 20 

Ideally, the output would be just an array:

 2,11,16,20 

So far, here's what I have, but I think it's a little over my head, given my limited skills:

 $string = " this is a string "; $string = rtrim($string); //just trim the right sides spaces $len = strlen($string); $is_prev_white = true; $result = ""; for( $i = 0; $i <= $len; $i++ ) { $char = substr( $string,$i,1); if(!preg_match("/\s/", $char) AND $prev_white){ $result .= $i.","; $prev_white = false; }else{ $prev_white = true; } } echo $result; 

I get: 2,4,11,16,20,22,24,26

+5
source share
6 answers

A simple but progressive solution with the preg_match_all and array_walk functions: Use the preg_match_all function with the PREG_OFFSET_CAPTURE flag:

PREG_OFFSET_CAPTURE . If this flag is passed, an adjacent line offset will also be returned for each matching match. Note that this changes the value corresponding to an array, where each element is an array consisting of a matched string with an offset of 0 and an offset of the string in the subject at offset 1.

 $string = " this is a string "; // subject preg_match_all("/\b\w+\b/iu", $string, $matches, PREG_OFFSET_CAPTURE); array_walk($matches[0], function(&$v){ // filter string offsets $v = $v[1]; }); var_dump($matches[0]); // the output: array (size=4) 0 => int 2 1 => int 11 2 => int 16 3 => int 20 

http://php.net/manual/en/function.preg-match-all.php

http://php.net/manual/en/function.array-walk.php

+1
source

Regular Expression Matching Php provides a flag to return te solutions instead of matched substrings. Use the following snippet:

 $hits = []; preg_match_all("/(?<=\s)\w/", " this is a string ", $hits, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE); $result = array_column ( $hits[0], 1 ); $s_result = join ( ", ", $result); echo $s_result; 

The regex pattern uses a positive lookbehind to find the first char after the space character. The array_column call retrieves the result data from the multidimensional array returned as a pattern matching description. join joins the elements of the array into a string, the selected delimiter turns it into a csv string.

See php docs for array_column and preg_match_all for details.

Live example here . According to this site, the solution works with php 5.5.0.

+1
source

You want the flag PREG_OFFSET_CAPTURE:

 $string = " this is a string "; preg_match_all('/(?:^|\s)([^\s])/', $string, $matches, PREG_OFFSET_CAPTURE); $result = $matches[1]; echo var_dump($result); 

Regular expression:

 (?:^|\s) // Matches white space or the start of the string (non capturing group) (^\s) // Matches anything *but* white space (capturing group) 

Passing PREG_OFFSET_CAPTURE does preg_match () or preg_match_all () return match as two-element arrays that contain both a matching string and a matching index in the search string. The result of the above code:

 array(4) { [0]=> array(2) { [0]=> string(1) "t" [1]=> int(2) } [1]=> array(2) { [0]=> string(1) "i" [1]=> int(11) } [2]=> array(2) { [0]=> string(1) "a" [1]=> int(16) } [3]=> array(2) { [0]=> string(1) "s" [1]=> int(20) } } 

So you can get an array of indices only with

 $firstChars = array_column($result, 1); 
+1
source

The pattern you are looking for is simple enough so that a regular expression is not necessary to match it. You can do this simply by going up the line.

 $l = strlen($string); $result = array(); // use this flag to keep track of whether the previous character was NOT a space $c = false; for ($i=0; $i < $l; $i++) { // if the previous character was a space and the current one isn't... if (!$c && $string[$i] != ' ') { // add current index to result $result[] = $i; } // set the 'not a space' flag for the current character $c = $string[$i] != ' '; } 
0
source

You can also use preg_split with two flags.

 $string = " this is a string "; $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE; // \W+ matches one or more non word characters $csv = implode(",", array_column(preg_split('/\W+/', $string, -1, $flags), 1)); 

  echo $ csv; 

2,11,16,20

If you need offset words, just remove the array_column and implode .

  $ res = preg_split ('/ \ W + /', $ string, -1, $ flags); 
0
source

Try this without regex. Hope this works for you.

 $str=" w this is a string "; echo "<pre>"; print_r(first_letter_index($str)); function first_letter_index($str) { $arr2 = array_map('trim',str_split($str)); $result=array(); foreach($arr2 as $k=>$v) { if(!empty($v) && empty($arr2[$k-1])) { $result[$k]=$v; } } return $result; } 
0
source

Source: https://habr.com/ru/post/1243873/


All Articles