【问题标题】:PHP get closest time to given array of times [duplicate]PHP获得最接近给定时间数组的时间[重复]
【发布时间】:2019-04-16 11:29:24
【问题描述】:

我有一个名为 $timeslots 的数组,其时隙如下:

array:32 [▼
  0 => "2018-12-15T12:00:00.0000000"
  1 => "2018-12-15T12:15:00.0000000"
  2 => "2018-12-15T12:30:00.0000000"
  3 => "2018-12-15T12:45:00.0000000"
  4 => "2018-12-15T13:00:00.0000000"
  5 => "2018-12-15T13:15:00.0000000"
  6 => "2018-12-15T13:45:00.0000000"
  7 => "2018-12-15T14:15:00.0000000"
  8 => "2018-12-15T14:30:00.0000000"
  9 => "2018-12-15T14:45:00.0000000"
  10 => "2018-12-15T15:00:00.0000000"
  11 => "2018-12-15T15:15:00.0000000"
  12 => "2018-12-15T15:30:00.0000000"
  13 => "2018-12-15T15:45:00.0000000"
  14 => "2018-12-15T16:15:00.0000000"
  15 => "2018-12-15T16:45:00.0000000"
  16 => "2018-12-15T17:00:00.0000000"
  17 => "2018-12-15T17:30:00.0000000"
  18 => "2018-12-15T17:45:00.0000000"
  19 => "2018-12-15T18:30:00.0000000"
  20 => "2018-12-15T18:45:00.0000000"
  21 => "2018-12-15T19:15:00.0000000"
  22 => "2018-12-15T19:45:00.0000000"
  23 => "2018-12-15T20:15:00.0000000"
  24 => "2018-12-15T20:45:00.0000000"
  25 => "2018-12-15T21:00:00.0000000"
  26 => "2018-12-15T21:15:00.0000000"
  27 => "2018-12-15T21:30:00.0000000"
  28 => "2018-12-15T21:45:00.0000000"
  29 => "2018-12-15T22:00:00.0000000"
  30 => "2018-12-15T22:15:00.0000000"
  31 => "2018-12-15T22:30:00.0000000"
]

另外,我有一个像这样的变量:

$expected_time = 2018-12-15T18:00:00.0000000; // this can be different value, so its not unique value

$expected_time 永远不会进入数组 $timeslots,但我需要找到最接近 $expected_time 的值...我该怎么做?

如何从数组$timeslots$expected_time 获取最接近的时隙值并计算以分钟为单位的差异?

有什么想法吗?

【问题讨论】:

  • 到目前为止您尝试过什么?编写foreach 循环并计算差异应该相当简单
  • 不,这不仅仅是区别。我知道这样做,问题是找到最接近的值给 $expected_time ...所以 $expected_time 每次都可以不同
  • 作为提示,如果将这些值转换为时间戳,则可以在数组中找到预期时间之间的哪两个。然后,您可以根据任何标准选择合适的广告位。
  • 你能解释一下为什么计算差异没有问题,但是找到最小距离的元素有问题吗?
  • @JonJ 用时间戳给我一个好主意。非常感谢!

标签: php arrays datetime difference php-carbon


【解决方案1】:

正如 Nico 在 cmets 中提到的,它非常简单。只是循环和计算时间差。

$timeslots = [...];
$expected_time = "2018-12-15T18:00:00.0000000";
$timestamp = strtotime($expected_time);
$diff = null;
$index = null;

foreach ($timeslots as $key => $time) {
    $currDiff = abs($timestamp - strtotime($time));
    if (is_null($diff) || $currDiff < $diff) {
        $index = $key;
        $diff = $currDiff;
    }
}

echo $timeslots[$index];

【讨论】:

  • 我会将strtotime($expected_time) 移到循环外并使其成为变量。您这样做的方式将根据相关数组解析比需要多 31 倍的日期。
【解决方案2】:

这里有一个适合您要求的解决方案:

function findClosestDate($expectedDate,$dates)
{

    $differenceInMinutes = null; 
    $expectedDate = new DateTime($expectedDate);
    $expectedDateEpoch = $expectedDate->getTimestamp();
    $returnIndex = -1;

    for($i = 0; $i<count($dates); $i++)
    {
        $dateObject = new DateTime($dates[$i]);
        $dateEpoch = $dateObject->getTimestamp();
        $difference = abs($expectedDateEpoch-$dateEpoch);
        $difference = $difference/60;
        if($differenceInMinutes === null || $difference < $differenceInMinutes)
        {
            $differenceInMinutes = $difference;
            $returnIndex = $i;
        }
    }

    return array(
        "closest" => $dates[$returnIndex],
        "difference" => $differenceInMinutes
    ) ;
}

这利用DateTime 类来创建DateTime 对象并获取相应的timestamp。然后通过expectedDatedates 数组中的条目之间的绝对差来计算分钟数。遍历整个数组后,最接近的匹配项和差值在一个数组中返回。

【讨论】:

    【解决方案3】:

    因为您的列表已经排序 - 您可以将元素放入数组并再次使用排序 - 并且在每次迭代中计算差异会快得多。

    <?php
    $timeslots = [
        ...
    ];
    
    $expected_time = "2018-12-15T18:00:00.0000000";
    $counter = count($timeslots);
    $timeslots = array_flip($timeslots);
    $timeslots[$expected_time] = $counter;
    ksort($timeslots);
    
    while (key($timeslots) !== $expected_time) {
        $prev = key($timeslots);
        next($timeslots);
    }
    
    next($timeslots);
    $next = key($timeslots);
    
    $expected_time = new \DateTime($expected_time);
    $closestDiff = min(($expected_time)->diff(new \DateTime($prev)), (new \DateTime($next))->diff($expected_time));
    var_dump($closestDiff->i);
    

    【讨论】:

    • 为什么不用array_search 而不是循环?
    • 我需要当前的上一个和下一个 - 最好在 doublelinkedlist 上使用它 - 但我们有一个数组:)
    猜你喜欢
    • 2012-02-03
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多