LoginSignup
2
0

More than 3 years have passed since last update.

[PHP]explode()の「区切り文字列」配列版

Posted at

やりたいこと

explode('_', '111_222');
とするだけで、111222に分割してくれる便利なexplodeさん。
上記の'_'の部分を、配列で渡したい、みたいな欲求が生まれた。

具体的には、
explode_ex(['_', '-'], '111_222-333');
とした場合に、戻り値がarray(3) {[0]=>'111',[1]=>'222',[2]=>'333'}となってほしい。

※なぜこんなことを思い立ったのかが思い出せない。

作った関数

引数は基本的に、本家explodeさんに準拠。delimiterだけ配列OKにする。

/**
 * explodeのdelimiterが配列でも大丈夫版
 *
 * @param array|string $delimiter 区切り文字列
 * @param string       $string    入力文字列
 * @param int          $limit
 * @return array
 */
function explode_ex($delimiter, $string, $limit = PHP_INT_MAX) {
    if (is_string($delimiter)) {
        // 文字列型を渡されたら、普通にexplode
        return explode($delimiter, $string, $limit);
    } else if (!is_array($delimiter)) {
        // stringでもarrayでも無ければ、処理せずに返却
        return [$string];
    }

    $delete = 0;
    if (intval($limit) === 0) {
        // limitに0が入れられていた場合、1にしておく(explode準拠)
        $limit = 1;
    } else if (intval($limit) < 0) {
        // マイナスの時は、最後の -limit 個の要素を除く全ての構成要素が返されます
        $delete = -1 * $limit;
        $limit = PHP_INT_MAX;
    }

    $list = []; // 分割した後の内容はここへ

    // 上限数まで分割
    for ($count = 0;$count < $limit;$count++) {
        // 複数あるdelimiterのうち、最初に出てくる文字を探す
        $min = strlen($string);
        $target = '';
        foreach ($delimiter as $search) {
            $position = strpos($string, $search);
            if ($position !== false && $min > $position) {
                $min = $position;
                $target = $search;
            }
        }

        // 見つからない or 次で上限数に達してしまう場合
        if ($target === '' || ($count + 1) === $limit) {
            // 返却用配列にそのまま入れる
            $list[] = $string;

            // ループ終了
            break;
        }

        // 最初に出てくる文字で2分割し、前半を返却配列へ、後半は更に分割
        list($list[], $string) = explode($target, $string, 2);
    }

    // 末尾削除
    if ($delete > 0) {
        for ($i = 0;$i < $delete;$i++) {
            array_pop($list);
        }
    }

    return $list;
}

動作結果

var_dump(explode_ex(['/', '-', ':', ' '], '2019/07-20 00:20:30'));
// result ->array(6) { [0]=> string(4) "2019" [1]=> string(2) "07" [2]=> string(2) "20" [3]=> string(2) "00" [4]=> string(2) "20" [5]=> string(2) "30" }

var_dump(explode_ex(['/', '-', ':', ' '], '2019/07-20 00:20:30', 3));
// result ->array(3) { [0]=> string(4) "2019" [1]=> string(2) "07" [2]=> string(11) "20 00:20:30" }

var_dump(explode_ex(['/', '-', ':', ' '], '2019/07-20 00:20:30', -2));
// result ->array(4) { [0]=> string(4) "2019" [1]=> string(2) "07" [2]=> string(2) "20" [3]=> string(2) "00" }

var_dump(explode_ex(['あ','い','う'], 'qazかXSWあedcきVFRいtgbきNHYうujmくLKI'));
// result ->array(4) { [0]=> string(13) "qazかXSW" [1]=> string(13) "edcきVFR" [2]=> string(13) "tgbきNHY" [3]=> string(13) "ujmくLKI" }
2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0