ねえデイブ、あなたはこれが来るのを見るつもりはない.
php > $kanji = '漢漢漢字漢字私私字私字漢字私漢字漢字私';
php > $not_kanji = 'aaabcccbbc';
php > $pattern = '/(.)\1+/u';
php > echo preg_replace($pattern, '$1', $kanji);
漢字漢字私字私字漢字私漢字漢字私
php > echo preg_replace($pattern, '$1', $not_kanji);
abcbc
何、私がまた使うと思っmb_substr
たの?
正規表現で言えば、任意の 1 文字を探し、次にその同じ文字の 1 つ以上のインスタンスを探します。一致した領域は、一致した 1 文字に置き換えられます。
このu
修飾子は、PCRE で UTF-8 モードをオンにします。このモードでは、8 ビット文字の代わりにUTF-8 シーケンスを処理します。処理中の文字列が既に UTF-8であり、 PCRE が Unicode サポート付きでコンパイルされている限り、これは問題なく動作するはずです。
ねえ、ちょっと聞いてよ!
$not_kanji = 'aaabbbbcdddbbbbccgggcdddeeedddaaaffff';
$l = mb_strlen($not_kanji);
$unique = array();
for($i = 0; $i < $l; $i++) {
$char = mb_substr($not_kanji, $i, 1);
if(!array_key_exists($char, $unique))
$unique[$char] = 0;
$unique[$char]++;
}
echo join('', array_keys($unique));
これは、シャッフル コードと同じ一般的なトリックを使用します。文字列の長さを取得し、 を使用mb_substr
して一度に 1 文字ずつ抽出します。次に、その文字を配列のキーとして使用します。PHP の位置配列を利用しています。キーは、定義された順序でソートされます。文字列を調べてすべての文字を特定したら、キーを取得して、文字列に出現したのと同じ順序で結合します。この手法から、1 文字あたりの文字数も取得できます。
mb_str_split
と一緒に行くようなものがあれば、これはずっと簡単だったでしょうstr_split
。
(ここに漢字の例はありません。コピー/貼り付けのバグが発生しています。)
ここで、これを試着してサイズを確認します。
function mb_count_chars_kinda($input) {
$l = mb_strlen($input);
$unique = array();
for($i = 0; $i < $l; $i++) {
$char = mb_substr($input, $i, 1);
if(!array_key_exists($char, $unique))
$unique[$char] = 0;
$unique[$char]++;
}
return $unique;
}
function mb_string_chars_diff($one, $two) {
$left = array_keys(mb_count_chars_kinda($one));
$right = array_keys(mb_count_chars_kinda($two));
return array_diff($left, $right);
}
print_r(mb_string_chars_diff('aabbccddeeffgg', 'abcde'));
/* =>
Array
(
[5] => f
[6] => g
)
*/
これを 2 回呼び出す必要があります。2 回目は、左側の文字列を右側に、右側の文字列を左側に配置します。出力は異なります -array_diff
右側から欠けているものを左側に表示するだけなので、ストーリー全体を取得するには 2 回実行する必要があります。