2016-02-25 48 views
5

に文字列の各文字の位置を取得しますこのような文字の位置:PHPは、例えば、文字列、与えられた配列

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

理想的には出力がちょうど配列のようになります。

2,11,16,20 

はこれまでのところ、ここで私が持っているものであるが、私は、これは私の限られたスキル与えられたビット私の頭の上にあると思う:

$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; 

私は取得しています: 2,4,11,16,20,22,24を、 26

答えて

1

シンプルな、しかしpreg_match_allarray_walk機能を持つプログレッシブ :)溶液でちょうどインデックスの配列を得ることができますpreg_match_all機能付きPREG_OFFSET_CAPTUREフラグ:

PREG_OFFSET_CAPTURE:このフラグが渡された場合、出現するすべての一致に対して、付加文字列オフセットも返されます。これはすべての要素がマッチした文字列からなるアレイに0をオフセットし、その文字列が被験体へのオフセットである配列にマッチの値を変更することに留意されたいで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

+0

これは正解ですが、私が試していた形式の '2,11,16,20'にそれらを入れることはできません。示されているようにcsvリストに到達する最も簡単な方法は何ですか? –

+0

@TripleCでは、文字列のオフセットを持つ配列をCSV文字列に変換する最も簡単な方法は、 'implode'関数を使うことです:' var_dump(implode( "、$ matches [0]);' 'string ' 11,16,20'' – RomanPerekhrest

+0

私はもう1つの質問がありました。私の言葉の中には、例えば 'ca#t'のようなシンボルがあります。この正規表現を修正して、シンボルを含む単語を含めるにはどうしたらいいですか? –

0

あなたが探しているパターンは、それにマッチするのに正規表現が必要ないほど単純です。文字列をループするだけでこれを行うことができます。

$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] != ' '; 
} 
1

php regex matchingは、一致する部分文字列の代わりにteオフセットを返すフラグを提供します。次のスニペットを使用します。

$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; 

正規表現パターンは、空白文字の後に最初の文字を見つけるために正のlookbehindを使用します。 array_columnを呼び出すと、パターン一致の説明として返された多次元配列から結果データが抽出されます。 joinは配列要素を文字列に連結し、選択されたセパレータはそれをcsv行に変換します。

詳細については、array_columnおよびpreg_match_allのphpドキュメントを参照してください。

ライブの例here。このサイトによると、このソリューションはPHP 5.5.0で動作します。

+0

文字列がスペースではなく単語で始まる場合、これは機能しますか? –

+0

@ Don'tPanic部分的に、最初のオカレンスは見つかりません。残念なことに、lookbehain引数は固定長でなければなりません。つまり、標準的な代入である '(^ | \ s)'は動作しません。ヒントのためのThx。 – collapsar

1

あなたは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); 

正規表現は、次のとおり

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

渡すPREG_OFFSET_CAPTUREにするpreg_match()またはpreg_match_all()戻り、一致の両方を含む2要素アレイとして一致させます検索された文字列内の一致するインデックスを返します。上記のコードの結果は次のとおりです。 用途:

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) } 
} 

だから、

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

文字列がスペースではなく単語で始まる場合、これは機能しますか? –

+0

@ Don'tPanic良い点!私はそれに応じて正規表現を更新しました。 – AmericanUmlaut

0

また、次の2つのフラグでpreg_splitを使用することができます。

$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

あなたが持つ単語がオフセットが必要な場合は、単にarray_columnimplode一部を除去。

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

0

のは、正規表現せずにこれを試してみましょう。私はそれがあなたのために働くことを望みます。

$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; 
} 
関連する問題