簡體   English   中英

PHP:檢查數組元素是否存在跳過一個級別

[英]PHP: Check if array element exists skipping one level

我正在嘗試檢查數組元素是否已經存在,如果不存在,我需要創建一個數組元素,只填充一個值,第二個值設置為null。 增加的復雜性是我需要在檢查數組時忽略第二級而不必再次遍歷數組,因為它可能是一個非常大的數組。

我的數組看起來像這樣:

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]) { ,是否可以忽略$day元素和$store元素之間的第二級,以便它將檢查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)));
} 

我會遍歷所有日期。 對於每一天,循環遍歷您希望找到的所有商店編號。 使用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

正如Rizier123建議的那樣,你可以使用array_column()。 Yous可以編寫一個簡單的函數來接受存儲數,通過引用和日期接受歷史數組:

$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
<?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 )。
所以你的代碼片段就像上面的代碼一樣。

我編輯了代碼,將數據附加到主日期元素而不是根目錄

一些嵌套循環應該這樣做,我想你可能想要創建一個新的日期元素,如果它在歷史中也不存在。

代碼評論:

<?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] => 
                )

        )

)

感謝來自@ trincot評論的幫助,我設法得到了我想要做的事情,使用商店ID作為數組中的鍵,下面的工作代碼。

$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)));
}

由於您願意更改數據結構,因此只需幾行簡單的代碼就可以實現另一種非常酷的方法。 首先將數據源更改為新的形狀,其中商店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,
    ],
];

現在你所要做的就是在你的源代碼中循環,並在數組上使用+運算符添加任何缺少的存儲(它添加了缺少的鍵)

$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_combined通過將第一個參數用作鍵,將第二個參數用作值來返回數組

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM