

あるサービスで、商品（３種類）とエリアにより、価格を決定する方法を考えています。  
以下のように、価格テーブルを作ることにより、みやすく、価格を返す関数作れるかなと思っています。

商品コード 12,32,33 の三種類があり、エリアが以下のように分かれており、  
この二つから価格を決定する良い方法を考えているのですが・・・

中々可読性を高くする良い方法が思い浮かびません 教えてください。

//例えば、  
配列の順番から、0=12 , 1 = 32, 2 = 33とした場合  
対象の場所＝2 商品12  
対象の場所のエリアはCHUO  
1700が価格。

対象の場所＝8 商品32  
対象の場所のエリアはMINAMIなので  
990が価格となるような感じです。

[code]

    $targetPlace = 2
    
    class PRICE{
        const HIGSHI = [5,6,7];
        const CHUO = [1,2,4];
        const MINAMI = [8,9,10,11];
    
        const PRICES_TABLE = array(HIGSHI => [2200,3200,4400], CHUO => [1700,1900,4000] MINAMI=>[440,990,1000]);
    
        public static  $tokyo_array = array(
            '1'=>'千代田区',
            '2'=>'港区',
            '3'=>'渋谷区',
            //...
            '23'=>'板橋区',
        }
    
    
[/code]

[code]

    PRICE::PRICES_TABLE[[$targetPlace]][0];
    
[/code]


CC BY-SA 4.0
2021-06-16T04:52:15.937
77594
2021-06-17T04:19:38.910
2021-06-16T08:25:12.117
44839
44839
question
php
PHP Arrayに入れた値を取得する方法


正規化を要する複雑なデータ構造ならばリレーショナルデータベース(RDB)を使用した方が良いように思います。

RDBを使うほど大掛かりにしたくないけれど第三者がコードリーディングした時の可読性を上げたいのならば連想配列やメソッド、コメントを使ってコードに意味を持たせつつ整形する方法が保守や拡張しやすい正攻法ではないでしょうか。

[code]

    <?php
    class Price {
        //エリアごとに23区の区コードを振り分ける
        const AREAS = array('東'   => [5,6,7],
                            '中央' => [1,2,4],
                            '南'   => [8,9,10,11]);
        //エリアと商品コードごとに一意の価格を振り分ける
        const PRICES = array('東'   => array(12 => 2200, 32 => 3200, 33 => 4400),
                             '中央' => array(12 => 1700, 32 => 1900, 33 => 4000),
                             '南'   => array(12 =>  440, 32 =>  990, 33 => 1000));
        //区コードと商品コードから価格を取得する
        public static function getPrice($ward, $item) {
            foreach(array_keys(self::AREAS) as $area) {
                if(in_array($ward, self::AREAS[$area]) && array_key_exists($item, self::PRICES[$area])) {
                    //エリアの区コードに $ward を含む場合は商品コードに該当する価格を返す
                    return self::PRICES[$area][$item];
                }
            }
            //todo 該当が存在しない場合のエラー処理を追記すること(この例では-1を返す)
            return -1;
        }
    }
    
    echo Price::getPrice(2, 12)."\n"; // 1700
    echo Price::getPrice(8, 32)."\n"; //  990
    echo Price::getPrice(5, 13);      //   -1 (存在しないキー)
    ?>
    
[/code]


CC BY-SA 4.0
2021-06-16T15:14:59.813
77602
2021-06-17T04:19:38.910
2021-06-17T04:19:38.910
9820
9820
77594
answer


以下では、価格テーブル(`PRICE::$priceTable`)を作成して memoize(メモ化) しています。

[code]

    class PRICE {
      private const TOKYO_AREA = [
        [5, 6, 7],       // EAST
        [1, 2, 4],       // CENTRAL
        [8, 9, 10, 11],  // SOUTH
      ];
    
      private const GOODS_CODE = [12, 32, 33];
      private const _PRICES_TABLE = [
        [2200, 3200, 4400],  // EAST
        [1700, 1900, 4000],  // CENTRAL
        [ 440,  990, 1000],  // SOUTH
      ];
    
      private static $priceTable = null;
      public static function PRICES_TABLE() {
        if (self::$priceTable === null) {
          $i = 0;
          self::$priceTable = array_reduce(
            self::TOKYO_AREA,
            function ($result, $item) use(&$i) {
              array_map(function ($a) use(&$result, &$i) {
                $result[$a] = array_combine(
                    self::GOODS_CODE, self::_PRICES_TABLE[$i]);
              }, $item);
              $i++;
              return $result;
            }, array());
        }
    
        return self::$priceTable;
      }
    }
    
    // Testing
    foreach([[2, 12], [8, 32], [5, 33]] as $v) {
      printf("PRICE::PRICES_TABLE()[{$v[0]}][{$v[1]}] = %4d\n",
             PRICE::PRICES_TABLE()[$v[0]][$v[1]]);
    }
    
    // 実行結果
    PRICE::PRICES_TABLE()[2][12] = 1700
    PRICE::PRICES_TABLE()[8][32] =  990
    PRICE::PRICES_TABLE()[5][33] = 4400
    
[/code]


CC BY-SA 4.0
2021-06-16T23:24:19.777
77609
2021-06-16T23:24:19.777
77594
answer