2016-06-27 12 views
3

配列要素がすでに存在するかどうかを確認しようとしていますが、そうでない場合は、値が1つだけ設定された配列要素を作成し、 nullにする複雑さが増すということは、配列をもう一度ループすることなく配列をチェックしながら2番目のレベルを無視する必要があることです。これはかなり大きな配列になる可能性があるからです。PHP:配列要素が1つのレベルをスキップしているかどうかを調べる

私の配列は次のようになります。

Array 
(
    [2016-05-28] => Array 
    (
     [0] => Array 
     (
      [store] => 1 
      [price] => 12 
     ) 
     [1] => Array 
     (
      [store] => 7 
      [price] => 18 
     ) 
     [2] => Array 
     (
      [store] => 9 
      [price] => 
     ) 
    ) 
) 

私は店の値xを持つ既存の要素があるかどうかを確認しようとしているし、それが存在しない場合、私はそれならば、新しい要素を作成します私はそれを無視して移動します。

この例では、$day$storeという変数をハードコードしていますが、これは通常forループで作成され、次にforループ内で以下のスニペットが実行されます。

マイコード:

$day = '2016-05-28'; 
$store = 8; 

if (!$history[$day][][$store]) { 
    $history[$day][] = array(
     "store" => $store 
     , "price" => null 
    ); 
} 

問題は要素がif (!$history[$day][][$store]) {が存在するかどうかをチェックの上で、それはそれがstore要素をチェックするように$day要素と$store要素との間に第二のレベルを無視することが可能ですそれが存在するかどうかを確認するには、ワイルドカードを使用するか、in_arrayを使用できますか?

ここには、私が現在使用している完全なコードがあります。

$setPriceHistoryData = $daoObj->getSetPriceHistoryData($set['id']); 
$chartDays = date('Y-m-d', strtotime('-30 days')); 
$priceHistoryData = array(); 
$endDay = date('Y-m-d'); 

while ($chartDays <= $endDay) { 
    for ($i = 0; $i < count($setPriceData["price_history_store_data"]); $i++) { 
     for ($j = 0; $j < count($setPriceHistoryData); $j++) { 
      if ($setPriceData["price_history_store_data"][$i]["id"] == $setPriceHistoryData[$j]["vph_store"] 
       && $chartDays == $setPriceHistoryData[$j]["vph_date"]) { 
       $priceHistoryData[$chartDays][] = array(
        "store" => $setPriceHistoryData[$j]["vph_store"] 
        , "price" => $setPriceHistoryData[$j]["vph_price"] 
       ); 
      } else { 
       if (!$priceHistoryData[$chartDays][]["store"]) { 
        $priceHistoryData[$chartDays][] = array(
         "store" => $setPriceHistoryData[$j]["vph_store"] 
         , "price" => null 
        ); 
       } 
      } 
     } 
    } 

    // Increment day 
    $chartDays = date('Y-m-d', strtotime("+1 day", strtotime($chartDays))); 
} 
+1

配列をループし、ストア値を1次元配列に取得する必要があります。いくつかのループでこれを行うか、代わりに 'array_column()'を使うことができます。次のようなものがあります: 'print_r(array_column(function($ v){return array_column($ v、" store ");}、$ history)、0));' – Rizier123

+2

パフォーマンスが向上し、あなたの履歴構造を別々に編成する場合は、値の代わりにキーの中にストアIDを入れてください - '' 2016-05-28 "=> [1 => 12,7 => 18,9 => null]、...'。 – trincot

+0

@trincot、完璧な、正しい方向に私を指差し、私が今すぐ必要なすべての作業! – llanato

答えて

0

ありがとう:あんたは、ストアNUM、参照によって歴史アレイと一日を受け入れるだろう単純な関数を書くことができ配列のキーとして、以下の作業コードを使用します。

$setPriceHistoryData = $daoObj->getSetPriceHistoryData($set['id']); 
$chartDays = date('Y-m-d', strtotime('-30 days')); 
$endDay = date('Y-m-d'); 
$priceHistoryData = array(); 

while ($chartDays <= $endDay) { 
    for ($i = 0; $i < count($setPriceData["price_history_store_data"]); $i++) { 
     $store = $setPriceData["price_history_store_data"][$i]["id"]; 

     for ($j = 0; $j < count($setPriceHistoryData); $j++) {      
      if ($store == $setPriceHistoryData[$j]["vph_store"] 
       && $chartDays == $setPriceHistoryData[$j]["vph_date"] 
       && !isset($priceHistoryData[$chartDays][$store])) { 
       $priceHistoryData[$chartDays][$store] = $setPriceHistoryData[$j]["vph_price"]; 
      } else { 
       if (!isset($priceHistoryData[$chartDays][$store])) { 
        $priceHistoryData[$chartDays][$store] = null; 
       } 
      } 
     } 
    } 

    // Increment day 
    $chartDays = date('Y-m-d', strtotime("+1 day", strtotime($chartDays))); 
} 
2

私はすべての日付をループします。毎日、探しているすべての店舗番号をループします。必要な店舗を見つけるにはarray_filterを使用してください。必要なストアが見つからない場合は追加します。

$required_stores = [1,2,3,4]; // stores you wish to add if missing  
$source = [ 
    '2016-06-15'=>[ 
     ['store'=>1,'price'=>10],['store'=>2,'price'=>10], 
    ], 
    '2016-06-16'=>[ 
     ['store'=>1,'price'=>10],['store'=>3,'price'=>10], 
    ], 
    '2016-06-17'=>[ 
     ['store'=>3,'price'=>10],['store'=>4,'price'=>10], 
    ], 
];  
//go through all dates. Notice we pass $stores as reference 
//using "&" This allows us to modify it in the forEach 
foreach ($source as $date => &$stores):  
    foreach($required_stores as $lookfor): 
     //$lookfor is the store number we want to add if it's missing 

     //will hold the store we look for, or be empty if it's not there 
     $found_store = array_filter(
      $stores, 
      function($v) use ($lookfor){return $v['store']===$lookfor;} 
     ); 

     //add the store to $stores if it was not found by array_filter 
     if(empty($found_store)) $stores[] = ['store'=>$lookfor,'price'=>null]; 
    endforeach; 
endforeach; 

// here, $source is padded with all required stores 
0
<?php 
$history = array(); // Assuming that's array's identifier. 
$history['2016-05-28'] = array (
    array('store' => 1, 'price' => 12), 
    array('store' => 7, 'price' => 18), 
    array('store' => 9, 'price' => 20) 
); 
// variables for the if condition 
$day = '2016-05-28'; 
$store = 8; 
$match_found = FALSE; 

foreach($history[$day] as $element) { 
    if ($element['store'] == $store) { 
     $match_found = TRUE; 
    } 
    else { 
     continue; 
    } 
} 

if ($match_found == TRUE) { 
    // I included a break statement here. break works only in iterations, not conditionals. 
} else { 
    array_push($history[$day], array('store' => $store, 'price' => null)); 
    // I was pushing to $history[$date] instead of $history[$day] since the variable I created was $day, NOT $date 
} 

私は、キーと値の宣言は、いくつかのエラーを与えていたという理由だけでPHPスニペットを書き直しました。たとえば、2016-05-28のキー要素は、PHPの仕様(http://php.net/manual/en/language.types.array.php)に従って、文字列または整数のいずれかとします。
コードスニペットは上のコードのように表示されます。


は、私が代わりに

+0

'構文エラー、予期しない '$ store'(T_VARIABLE)9行目' –

+0

セミコロンを修正しても、これは日付要素の中ではなく配列のルートに追加されます... –

+0

申し訳ありません、私の間違いは、 25行目 – cr05s19xx

0

カップルネストされたループは、それを行う必要がありますルートの主な日付要素にデータを追加するためのコードを編集した、と私はそれはdoesnの場合は、新しい日付の要素を作成したいかもしれないと思いました歴史の中にも存在する。

コードがコメントされています

<?php 
$history = Array 
(
    '2016-05-28' => Array 
    (
     0 => Array 
     (
      'store' => 1, 
      'price' => 12 
     ), 
     1 => Array 
     (
      'store' => 7, 
      'price' => 18 
     ), 
     2 => Array 
     (
      'store' => 9, 
      'price' => null 
     ) 
    ) 
); 

print_r($history); 

$day = '2016-05-28'; 
$store = 8; 

// loop through dates 
foreach ($history as $key=>&$date){ 

    // scan for date 
    $found_date = false; 
    if ($key != $day) continue; 
    $found_date = true; 

    // scan for store 
    foreach ($date as $item){ 
    $found_store = false; 
    if ($item['store'] != $store) continue; 
    $found_store = true; 
    // stop looping if store found 
    break; 
    } 

    // create null element 
    if (!$found_store) { 
     $date []= array(
      "store" => $store 
      , "price" => null 
    ); 
    } 

    // stop looping if date found 
    break; 

} 

// if date not found, create all elements 
if (!$found_date) { 
    $history[$day]= array(
    0 => array(
     "store" => $store 
     , "price" => null 
    ) 
); 
} 

print_r($history); 

前:

Array 
(
    [2016-05-28] => Array 
     (
      [0] => Array 
       (
        [store] => 1 
        [price] => 12 
       ) 

      [1] => Array 
       (
        [store] => 7 
        [price] => 18 
       ) 

      [2] => Array 
       (
        [store] => 9 
        [price] => 
       ) 

     ) 

) 

後:

Array 
(
    [2016-05-28] => Array 
     (
      [0] => Array 
       (
        [store] => 1 
        [price] => 12 
       ) 

      [1] => Array 
       (
        [store] => 7 
        [price] => 18 
       ) 

      [2] => Array 
       (
        [store] => 9 
        [price] => 
       ) 

      [3] => Array 
       (
        [store] => 8 
        [price] => 
       ) 

     ) 

) 
2

Rizier123が示唆したように、あなたは)(array_columnで行くことができます。私は店のIDを使用して行うようにしようとしていたものを手に入れることに成功し、@ trincotさんのコメントから支援する

$history = [ 
    '2016-05-28' => [ 
     ['store' => 1, 'price' => 23], 
     ['store' => 2, 'price' => 23], 
     ['store' => 3, 'price' => 23] 
    ] 
]; 
$store = 8; 
$day  = '2016-05-28'; 
function storeHistory($store, &$history, $day) 
{ 
    if (! isset($history[$day])) { 
     return false; 
    } 
    $presentStores = array_column($history[$day], 'store'); 
    if (! in_array($store, $presentStores)) { 
     $history[$day][] = ['store' => $store, 'price' => null]; 
    } 
} 

storeHistory($store, $history, $day); 
var_dump($history); 

array (size=1) 
    '2016-05-28' => 
    array (size=4) 
     0 => 
     array (size=2) 
      'store' => int 1 
      'price' => int 23 
     1 => 
     array (size=2) 
      'store' => int 2 
      'price' => int 23 
     2 => 
     array (size=2) 
      'store' => int 3 
      'price' => int 23 
     3 => 
     array (size=2) 
      'store' => int 8 
      'price' => null 
0

データ構造を変更しても構わないと思うので、コードのほんの数行で、本当にクールなアプローチができます。まず、店舗IDがキーであり、価格が値

$history = [ 
    '2016-06-15'=>[ 
     1=>10, 2=>10, //On June 15, store 1 had price 10 
    ], 
    '2016-06-16'=>[ 
     1=>10, 3=>10, 
    ], 
    '2016-06-17'=>[ 
     3=>10, 4=>10, 
    ], 
]; 

は、今あなたがしなければならないすべてはあなたのソース内の日を循環されされている新しい形にデータソースを変更して使用して、欠落している店舗を追加キーおよび値としての第2のパラメータとして、最初のパラメータを使用して、アレイ上+オペレータ(それが欠けているキーを追加)

$required_stores = [1,2,3,4]; // stores you wish to add if missing 

//will be [1=>null, 2=>null, 3=>null, 4=>null] 
$required_keys = array_combine(
       $required_stores, 
       array_fill(0,count($required_stores),null) 
    ); 
//go through each day and add required keys if they're missing 
foreach ($history as &$stores): 
    $stores += $required_keys 
endforeach; 

array_combinedreturns an array

+0

これは、アレイを再びループすることを必要とする結果、アレイを再びループする必要がなくなります。 – llanato

関連する問題