2つの問題(aとb)は同じ起源を持ち、パターンの各トークンはスペースで囲まれています。結果:a)トークンの1つが文字列の先頭または末尾にあるときは機能しません。 b)同じスペースを2回一致させることができないため、文字列に連続するトークンがあるときは機能しません。
これらの単語をすべて入れ替えて作成するアプローチは良くありません。パターンのパフォーマンスは、交替に新しいブランチを追加するたびに減少します(最悪の場合は文字列内の各位置正規表現エンジンはすべてのブランチをテストする必要があります)。
これは、文字列を非文字文字(たとえば、空白文字の各シーケンス、および非文字および非空白文字の各シーケンスでより正確に分割すること) 。完了したら、私はarray_diff
を使用して、不要な単語を削除します。 array_diff
の主な関心事は、キーを保持することです。この方法では、結果配列を生成するためにキーの隙間を見つけるだけで済みます。それはより複雑で長く見えます
場合でも、この方法は、はるかにスケーラブルである:
$str = 'I like to eat marshmallows while also listening to Metallica';
$words = [ '',
'also', 'and', 'any',
'I',
'facebook',
'the', 'to',
'where', 'while' ];
$parts = array_diff(preg_split('~(?=\PL)(?:\s+|[^\pL\s]+)~u', $str), $words);
$previousKey = false;
$temp = '';
$result = [];
foreach($parts as $k => $v) {
if ($previousKey === $k - 1) {
$temp .= " $v";
} else {
if ($previousKey)
$result[] = $temp;
$temp = $v;
}
$previousKey = $k;
}
if ($previousKey)
$result[] = $temp;
print_r($result);
demo
パターンの詳細:
~
(?=\PL) # improvement trick: make fail quickly positions with a letter
# without to test the whole pattern
(?:
\s+ # any sequence of white-spaces
| # OR
[^\pL\s]+ # any sequence of characters that are not letters or white-spaces
#
# This way: "eat marshmallows" returns:
# [0] => eat marshmallows
# but: "eat, marshmallows" returns:
# [0] => eat
# [1] =>
# [2] => marshmallows
# according to your original pattern
)
~u # make it able to deal with multibyte utf8 strings
より良いパターン:~\PL(?(?<=\s)\s*|[^\pL\s]*)~u
コードを共有してください... – Hossam
問題a):Tあなたの正規表現の冒頭で小さなスペースを削除します。 – Tuyen