質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

後方からの文字の切り出しがうまくいかない

受付中

回答 7

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 706

score 50

前提と期待値

$number = 123456789;


上記のような数字があり、これを後方から4桁, 4桁, 余りずつ切り出します。
$numberは正数です。PHPのバージョンは7.2.6です
期待値としては、

A => 6789
B => 2345
C => 1


このような形としたいです。

もし8桁しかない場合

A => 6789
B => 2345
C => ''


としたいです。

もし、4桁しかない場合

A => 6789
B => ''
C => ''


としたいです。

もし、5桁の場合

A => 6789
B => 5
C => ''


としたいです。

やった事

$number = 123456789;
$numberLen = strlen($number);

$a = substr($number, (-1 * $numberLen), 4);
$b = substr($number, (-1 * $numberLen) + 4, 4);
$c = substr($number, (-1 * $numberLen) + 8, 4);


上記のようなコードを書きました。
しかし、これでは$numberLenが3の場合、+4をすると、結果が1となる為、先頭から取得する形となります。
なので、ボツコードとなりました。

質問

期待値のような結果を得るにはどう実装すれば良いでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2019/01/26 17:18

    回答でネタをかいておいてなんだが
    13桁の場合の想定は?

    キャンセル

回答 7

+1

無理矢理感つよめ

$len=4;
$count=3;
$number = 123456789;
$arr = array_map(function($x) {
  return strrev($x);
},array_slice(
  array_merge(
    explode("\t",wordwrap(
      strrev(
        $number
        ),$len, "\t",true
      )
            ),array_fill(0,$count-2,"")
    ),0,$count
  )
);
print_r($arr);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/24 22:42

    wordwrap()がすごいです。

    array_map('strrev', array_slice…
    で行けると思います。

    キャンセル

+1

やりたいことがかなり都合がよい感じになっている気がするので、細分化してみた。

<?php
$number = 123456789;

//まず12個にする
$array = array_pad(str_split($number.""), -12, "");

//逆順にする(うしろから取りたいとの要件のため)
$rev = array_reverse($array);

//bufferする、4個ずつを3行に
$buffered = buffer($rev, 4, 3);

//各行を逆順にする(9876を6789にする)
$reversed = array_map('array_reverse', $buffered);

//連結する(56789のとき2つめを["","","","5"]->"5"にする
$joined = array_map(function($row){return implode("", $row);}, $reversed);
var_dump($joined);

//bufferする便利関数をしらなかったので自分で書いた。
function buffer($array, $unit, $count) {
   $normalized = array_pad($array, $unit * $count, "");
   $ret = [];
   for($outer = 0; $outer < $count; $outer++) {
       $ret[] = array_slice($normalized, $outer * $unit, $unit);
   }
   return $ret;
} 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/24 22:43

    配列にしたぶんだけ迂遠ですね。wordwrapとはね。bufferをそう解決する方法があるとは。

    キャンセル

  • 2019/02/08 17:24

    bufferするのにarray_chunkという便利関数があることを今日知った

    キャンセル

+1

色々妄想して書いてみた。

<?php
$numbers = [
    1234567890123456789,
    1000000000000000000,
    1234567890,
    234567890,
    34567890,
    4567890,
    567890,
    67890,
    7890,
    890,
    90,
    0,
];

function hoge($number){
    echo '$number = ' . $number . PHP_EOL;
    $str = 'a';
    $last_str = '';
    do {
        $last_str = $str;
        ${$str++} = sprintf("%'04d",($number % 10000));
        $number = (int)($number / 10000);
    } while($number >= 1);
    $str = in_array($str, ['a', 'b', 'c'])? 'd' : $str;
    for($i = 'a'; $i !== $str; ++$i){
        echo strtoupper( $i . ' => ');
        if(isset(${$i})) {
            if ($i !== $last_str) {
                echo ${$i};
            } else {
                echo (int)${$i};
            }
        } else {
            echo '\'\'';
        }
        echo PHP_EOL;
    }
}

foreach($numbers as $number){
    hoge($number);
}


色々後悔はしたw

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

4文字取り出して4文字削除してを繰り返すのはどうでしょう

<?php
$number = 123456789;
$number = "{$number}";
$list = [];
while(empty($number) === false) {
    $list[] = substr($number, -4);
    $number = substr_replace($number, '', -4);
}
var_dump($list);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/24 19:56

    桁が8以下の場合の命題に沿ってませんね

    キャンセル

  • 2019/01/24 20:05

    もしかして配列3つにしないといけないとかなら沿ってませんが、そういうことですか?

    キャンセル

0

<?php

ini_set('display_errors', true);
error_reporting(E_ALL);

$number = 1234567890;

$i = 0;
$arr = [];
while ($number > 0) {
    $res = fmod($number, pow(10, 4));
    $number = ($number - $res) / pow(10, 4);
    $arr[] = ($number > 0) ? sprintf('%04d', $res) : sprintf('%01d', $res);
}
var_dump($arr);

こういうことか

<?php

ini_set('display_errors', true);
error_reporting(E_ALL);

$number = 1234567890123;

$i = 0;
$arr = [];
while ($number > 0 && count($arr) < 3) {
    $res = fmod($number, pow(10, 4));
    if (count($arr) < 2) {
        $arr[] = ($number > 10000) ? sprintf('%04d', $res) : sprintf('%01d', $res);
    } else {
        $arr[] = $number;
    }
    $number = ($number - $res) / pow(10, 4);
}
var_dump($arr);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/26 17:11

    間違ってはいないと思うんだけど、どういうこと?

    キャンセル

  • 2019/01/26 17:16

    質問者のケースだと常に3つに分けたいように見える

    キャンセル

  • 2019/01/26 17:24

    ああ、なるほどw

    キャンセル

0

ほぼネタ。  スペースはトリムだ!!

コード

hi = fopen('php://stdin', "r");

while (true) {
    fscanf($hi, "%s", $n);
    if ($n == "END") break;

    $line = sprintf("%-20s",$n);
    echo $line;
    echo " : [ ";
    echo substr($line, 0, 4);
    echo " ";
    echo substr($line, 4, 4);
    echo " ";
    echo substr($line, 8);
    echo "]";
    echo PHP_EOL;
}

STDIN

1234567890123
123456789012
12345678901
1234567890
123456789
12345678
1234567
123456
12345
1234
123
12
1
END

STDOUT

1234567890123        : [ 1234 5678 90123       ]
123456789012         : [ 1234 5678 9012        ]
12345678901          : [ 1234 5678 901         ]
1234567890           : [ 1234 5678 90          ]
123456789            : [ 1234 5678 9           ]
12345678             : [ 1234 5678             ]
1234567              : [ 1234 567              ]
123456               : [ 1234 56               ]
12345                : [ 1234 5                ]
1234                 : [ 1234                  ]
123                  : [ 123                   ]
12                   : [ 12                    ]
1                    : [ 1                     ]

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

単純に3つに分けてみました。

  $a = substr($number, -4);
  $b = substr(substr($number, -8), 0, -4) ?: '';
  $c = substr($number, 0, -8) ?: '';

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る