PHP 搜索数组速度
PHP Search Array Speed
我想提前为冗长的问题道歉 post 但我想让你清楚地了解我的问题。感谢您的帮助。
我有一个名为 $data 的数组,格式如下:
...
...
给定任意开始日期,我需要在数组中搜索匹配日期:
//$holidays is an array with dates of public holidays which are not considered business days
$search_results = array();
$minDate = -10;
$maxDate = 100;
$start_date = "2015-02-25";
echo "Before loop: " . xdebug_time_index() . "<br>";
for ($i=$minDate; $i<=$maxDate; $i++) {
if (in_array_r(getBusinessDay(new DateTime($start_date), $holidays, $i), $data)){
$a_date = getBusinessDay(new DateTime($start_date), $holidays, $i);
$a_key = array_search($a_date, array_column($data, "date"));
$search_results[]=array($i, $data[$a_key]["data"]);
}
}
echo "After loop: " . xdebug_time_index() . "<br>";
var_dump($search_results);
但是,此代码片段在页面加载时可能 运行 10-15 次,每次执行需要很长时间(在较大的数组上至少需要 6 秒):
你能帮我理解是哪部分代码导致了这个延迟吗?我怎样才能加快这个过程?
预先感谢您的帮助。
以下是代码片段中使用的函数:
function getBusinessDay($startdate, $holidays, $days) {
$calculator = new BusinessDaysCalculator($startdate, $holidays, [BusinessDaysCalculator::SATURDAY, BusinessDaysCalculator::SUNDAY]);
$calculator->addBusinessDays($days);
$result = $calculator->getDate()->format('Y-m-d');
unset($calculator);
return $result;
}
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
以及 returns 下一个工作日(跳过周末和 $holidays 数组中的任何日期)的计算器:
class BusinessDaysCalculator {
const MONDAY = 1;
const TUESDAY = 2;
const WEDNESDAY = 3;
const THURSDAY = 4;
const FRIDAY = 5;
const SATURDAY = 6;
const SUNDAY = 7;
/**
* @param DateTime $startDate Date to start calculations from
* @param DateTime[] $holidays Array of holidays, holidays are no considered business days.
* @param int[] $nonBusinessDays Array of days of the week which are not business days.
*/
public function __construct(DateTime $startDate, array $holidays, array $nonBusinessDays) {
$this->date = $startDate;
$this->holidays = $holidays;
$this->nonBusinessDays = $nonBusinessDays;
}
public function addBusinessDays($howManyDays) {
$i = 0;
while ($i < abs($howManyDays)) {
if ($howManyDays < 0) {
$this->date->modify("-1 day");
} else {
$this->date->modify("+1 day");
}
if ($this->isBusinessDay($this->date)) {
$i++;
}
}
}
public function getDate() {
return $this->date;
}
private function isBusinessDay(DateTime $date) {
if (in_array((int)$date->format('N'), $this->nonBusinessDays)) {
return false; //Date is a nonBusinessDay.
}
foreach ($this->holidays as $day) {
if ($date->format('Y-m-d') == $day->format('Y-m-d')) {
return false; //Date is a holiday.
}
}
return true; //Date is a business day.
}
}
更新 1:
我将 $data 数组的结构更新为
循环到:
for ($i=$minDate; $i <= $maxDate; $i++) {
$day = getBusinessDay(new DateTime($start_date), $holidays, $i);
if (array_key_exists($day, $data)) {
$search_results[]=array($i, $data[$day]);
}
}
时间略有改善:
延迟的原因是array_key_exists吗?
更新 2:
这是 $holidays 数组(它是静态的,始终相同):
根据您的评论,日期列包含唯一值。
由于您仅在日期列上进行过滤,因此通过日期列为数组编制索引效率更高,因此您应该像这样重组数据:
$data = array(
'2015-02-19' => 1.35625,
'2015-02-20' => 1.4015,
'2015-02-23' => 0.9095,
'2015-02-24' => 1.0635,
'2015-02-25' => 1.08775,
'2015-02-26' => 0.947,
/* ... */
)
in_array
需要在整个数组中循环一个对应于一个日期的元素,这对于大型数组来说可能很慢。
使用这种结构,可以通过$data[$date]
.
访问数据,立即得到数据
我想提前为冗长的问题道歉 post 但我想让你清楚地了解我的问题。感谢您的帮助。
我有一个名为 $data 的数组,格式如下:
... ...
给定任意开始日期,我需要在数组中搜索匹配日期:
//$holidays is an array with dates of public holidays which are not considered business days
$search_results = array();
$minDate = -10;
$maxDate = 100;
$start_date = "2015-02-25";
echo "Before loop: " . xdebug_time_index() . "<br>";
for ($i=$minDate; $i<=$maxDate; $i++) {
if (in_array_r(getBusinessDay(new DateTime($start_date), $holidays, $i), $data)){
$a_date = getBusinessDay(new DateTime($start_date), $holidays, $i);
$a_key = array_search($a_date, array_column($data, "date"));
$search_results[]=array($i, $data[$a_key]["data"]);
}
}
echo "After loop: " . xdebug_time_index() . "<br>";
var_dump($search_results);
但是,此代码片段在页面加载时可能 运行 10-15 次,每次执行需要很长时间(在较大的数组上至少需要 6 秒):
你能帮我理解是哪部分代码导致了这个延迟吗?我怎样才能加快这个过程?
预先感谢您的帮助。
以下是代码片段中使用的函数:
function getBusinessDay($startdate, $holidays, $days) {
$calculator = new BusinessDaysCalculator($startdate, $holidays, [BusinessDaysCalculator::SATURDAY, BusinessDaysCalculator::SUNDAY]);
$calculator->addBusinessDays($days);
$result = $calculator->getDate()->format('Y-m-d');
unset($calculator);
return $result;
}
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
以及 returns 下一个工作日(跳过周末和 $holidays 数组中的任何日期)的计算器:
class BusinessDaysCalculator {
const MONDAY = 1;
const TUESDAY = 2;
const WEDNESDAY = 3;
const THURSDAY = 4;
const FRIDAY = 5;
const SATURDAY = 6;
const SUNDAY = 7;
/**
* @param DateTime $startDate Date to start calculations from
* @param DateTime[] $holidays Array of holidays, holidays are no considered business days.
* @param int[] $nonBusinessDays Array of days of the week which are not business days.
*/
public function __construct(DateTime $startDate, array $holidays, array $nonBusinessDays) {
$this->date = $startDate;
$this->holidays = $holidays;
$this->nonBusinessDays = $nonBusinessDays;
}
public function addBusinessDays($howManyDays) {
$i = 0;
while ($i < abs($howManyDays)) {
if ($howManyDays < 0) {
$this->date->modify("-1 day");
} else {
$this->date->modify("+1 day");
}
if ($this->isBusinessDay($this->date)) {
$i++;
}
}
}
public function getDate() {
return $this->date;
}
private function isBusinessDay(DateTime $date) {
if (in_array((int)$date->format('N'), $this->nonBusinessDays)) {
return false; //Date is a nonBusinessDay.
}
foreach ($this->holidays as $day) {
if ($date->format('Y-m-d') == $day->format('Y-m-d')) {
return false; //Date is a holiday.
}
}
return true; //Date is a business day.
}
}
更新 1: 我将 $data 数组的结构更新为
循环到:
for ($i=$minDate; $i <= $maxDate; $i++) {
$day = getBusinessDay(new DateTime($start_date), $holidays, $i);
if (array_key_exists($day, $data)) {
$search_results[]=array($i, $data[$day]);
}
}
时间略有改善:
延迟的原因是array_key_exists吗?
更新 2: 这是 $holidays 数组(它是静态的,始终相同):
根据您的评论,日期列包含唯一值。 由于您仅在日期列上进行过滤,因此通过日期列为数组编制索引效率更高,因此您应该像这样重组数据:
$data = array(
'2015-02-19' => 1.35625,
'2015-02-20' => 1.4015,
'2015-02-23' => 0.9095,
'2015-02-24' => 1.0635,
'2015-02-25' => 1.08775,
'2015-02-26' => 0.947,
/* ... */
)
in_array
需要在整个数组中循环一个对应于一个日期的元素,这对于大型数组来说可能很慢。
使用这种结构,可以通过$data[$date]
.