PHP 按时间排序数组并找到与 X 数字最接近的匹配项
Posted
技术标签:
【中文标题】PHP 按时间排序数组并找到与 X 数字最接近的匹配项【英文标题】:PHP Sorting Array by Time & finding the closest matches to X numbers 【发布时间】:2018-03-16 06:11:45 【问题描述】:我的目标不是将任何项目保存到数据库,而只是显示实时流。
我正在从赫芬顿邮报获取 RSS 提要
http://www.huffingtonpost.com/section/front-page/feed
我有一个包含 Huff 最近 50 篇文章的 WordPress 数组 (php)。
$rss = fetch_feed($feed_url);
我希望我的 RSS 提要每天仅显示 X
的唯一帖子总数。为了简单起见,我只是要显示最接近 24 / X
间隔的帖子。
为了演示,让我们使用 3。Feed 会吐出最接近 8 点、16 点(下午 2 点)和 24 点(午夜)或(0、8 和 16 点)发布的帖子。
在 PHP 中,如何通过发布的时间变量对对象数组进行排序,然后找到最接近该时间的帖子?现在我正在做一个非常迂回的方式,目前甚至无法正常工作。
这是我目前的逻辑:
if(function_exists('fetch_feed'))
$rss = fetch_feed(get_field('feed_url'));
if(!is_wp_error($rss)) : // error check
$maxitems = $rss->get_item_quantity(50); // number of items at 50
$rss_items = $rss->get_items(0, $maxitems);
endif;
// display feed items ?>
<h1><?php echo $rss->get_title(); ?></h1>
<?php
$coutner = 0;
$daily_max = 3; //how many unique feeds to display per day
$display_interval = floor(24 / $daily_max); //simple way to make even intervals
$posting_time = array(); //to store the times to post
foreach(range(0, $daily_max-1) as $i)
$posting_time[$i] = $display_interval * $i;
$post_interval = 0;
$date = new DateTime();
$today = date("G"); //getting the current day's hour
$time_adjust = $today / $display_interval;
//adjust the posting times order so that its circular
while($today > $posting_time[0])
$hold = array_pop($posting_time);
echo '<p>hold: ' . $hold;
array_unshift($posting_time,$hold);
$accessing = array_pop($posting_time);
?>
<dl>
<?php if($maxitems == 0) echo '<dt>Feed not available.</dt>';
else
foreach ($rss_items as $item) : ?>
<?php
//as soon as the first item is newer than post time, output it & count that time slot as being filled
$rss_item_hour = $item->get_date('G');
if($rss_item_hour > $accessing) ?>
<dt>
<a href="<?php echo $item->get_permalink(); ?>"
title="<?php echo $item->get_date('j F Y @ G'); ?>">
<?php echo $item->get_title(); ?>
</a>
</dt>
<dd>
<?php echo $item->get_description(); ?>
</dd>
<p>
<?php echo $item->get_date('j F Y | G');
?>
</p>
<?php $coutner = $coutner + 1;
$accessing = array_pop($posting_time);
elseecho '<p>else'; ?>
<?php endforeach; ?>
</dl>
<?php ?>
目前的主要错误是,有时while($today > $posting_time[0])
的循环移动会无限进行。而且循环似乎永远不会按计划进行。
【问题讨论】:
您是正确的,while 循环是问题,因为您从未在循环内更新 $today。如果它是真的,它将永远是真的,因为它永远不会被设置为其他任何东西。这绝对看起来过于复杂。我会尝试制定解决方案。 您是否真正关心显示的帖子在一天中的间隔是否均匀,或者只是为了简化它(提示:不关心要简单得多) ?从提要开始,您每天需要 3 件物品,还是过去 24 小时内只需要 3 件?是否保证每天/过去 24 小时内始终至少有 3 件商品? 那么,如果提要在凌晨 1 点检索,应该显示什么?由于下一个“里程碑”是上午 8 点,这意味着“最近的 4 个帖子”直到上午 8 点?那么,随着时间的推移,显示的帖子正在发生变化,因为可能会有更新的帖子“更接近”某个里程碑?阅读此内容,然后重新考虑您的问题,我会说xyproblem.info 既然您想要每 8 小时时间间隔(或 6 小时等...)的提要,您现在不应该只获取最后 x 小时的提要吗? 【参考方案1】:试试下面的例子,file_get_contents
用于这个例子来获取xml
。它将获取过去 8 小时内的所有提要。尝试使用DOMDocument
来处理xml
提要和Datetime
来管理所需的时间比较。
$hour_interval = 8;
$feeds = file_get_contents("http://www.huffingtonpost.com/section/front-page/feed");
$doc = new DOMDocument();
$doc->loadXML($feeds);
$items = $doc->getElementsByTagName('item');
$today = new DateTime("now",new DateTimeZone("-04:00")); // do mind the timezone it is the one set in the xml feeds so it is needed for correct time comparison
$nowTimestamp = $today->getTimestamp();
$today->modify('-'.$hour_interval.' hour');
$eightHoursBeforeTimestamp = $today->getTimestamp();
$lastEightHoursItems = [];
foreach ($items as $item)
$pubDate = $item->getElementsByTagName('pubDate')[0]->nodeValue;
$feedDate = new DateTime($pubDate);
$feedTimestamp = $feedDate->getTimestamp();
if($feedTimestamp<=$nowTimestamp and $feedTimestamp>=$eightHoursBeforeTimestamp)
array_push($lastEightHoursItems,$item);
$random_keys = array_rand($lastEightHoursItems,3);
$c = count($random_keys);
for($i=0;$i<$c;$i++)
echo $lastEightHoursItems[$random_keys[$i]]->getElementsByTagName('title')[0]->nodeValue;
echo $lastEightHoursItems[$random_keys[$i]]->getElementsByTagName('link')[0]->nodeValue;
echo $lastEightHoursItems[$random_keys[$i]]->getElementsByTagName('description')[0]->nodeValue;
echo $lastEightHoursItems[$random_keys[$i]]->getElementsByTagName('pubDate')[0]->nodeValue;
【讨论】:
您的代码看起来最简洁,所以我一直在尝试对其进行测试,但它并不限制显示的提要项目的数量。我真的不在乎显示什么内容,或者它与时间完美协调,只要提要“精简”内容总量并保持一致。 呃,我才意识到为什么这不起作用。 RSS 提要有问题,所以当它在中间跳过多个项目时,我认为你的工作方式与实际情况不同。你的在 8 小时内抓住一切。我正在尝试做的是限制在我的提要中显示的项目数量。我想要每天最多 X 篇文章。我任意设置了 3 的最大值,这意味着我希望 Feed 在 24 小时内显示 3 篇新文章。这意味着“均匀”的做法是将 24 小时除以 3 分为 8 小时段,并每天取最接近 8 小时标记的项目。 @jonbon 编辑了我的答案,因此每次刷新页面时,您都会在过去 8 小时内获得 3 篇随机文章【参考方案2】:将时间视为“一天中的秒数”(0 - 86400),以下几行将满足您的需求(简化示例):
<?php
$postTimes = array(1,600,953,1900,23500,27600,56000,72000);
echo "Closest match is: " + findMatch(24000, $postTimes); //23500
function findMatch($needle, $haystack)
$closest = null;
foreach ($haystack as $element)
if ($closest === null || abs($needle - $closest) > abs($element - $needle))
$closest = $element;
return $closest;
?>
最后你只需要实现:
getPostTimesAsSeconds($postArray); //foreach converting dates to seconds-array
和
pickPostBySecondsOfTheDay(23500); //foreach, finding the post matching the seconds of the day.
【讨论】:
【参考方案3】:我尝试根据您采用的方法构建解决方案,并使其变得更加简单。有许多边缘情况需要考虑,我稍后会解释,但我认为它仍然会按原样实现您应用的基本目标,但我确实做了一些假设。
...
<?php
$counter = 0;
$daily_max = 3; //how many unique feeds to display per day
$display_interval = floor(24 / $daily_max); //simple way to make even intervals
$posting_time = array(); //to store the times to post
// Create a list of time intervals largest to smallest ex. [16, 8, 0]
foreach(range($daily_max-1, 0) as $i)
$posting_time[] = $display_interval * $i;
?>
<dl>
<?php
if($maxitems == 0)
echo '<dt>Feed not available.</dt>';
else
foreach ($rss_items as $item)
if(count ($posting_time) == 0)
break;
//as soon as the first item is older than the most current post time, output it & count that time slot as being filled
$rss_item_hour = $item->get_date('G');
if($rss_item_hour < $posting_time[0])
?>
<dt>
<a href="<?php echo $item->get_permalink(); ?>"
title="<?php echo $item->get_date('j F Y @ G'); ?>">
<?php echo $item->get_title(); ?>
</a>
</dt>
<dd>
<?php echo $item->get_description(); ?>
</dd>
<p>
<?php echo $item->get_date('j F Y | G'); ?>
</p>
<?php
$counter++;
array_pop($posting_time);
else
// Debug message
?>
</dl>
...
好的,由于我无权访问您的 fetch_feed 数据,因此未经测试,但如果有错误,我很乐意更新。
这会选择按您指定的时间间隔粗略划分的帖子,但它不会进行任何检查以确定它们与这些边界的接近程度。例如,如果最新的帖子是在 16:01,它将被跳过以支持 16:00 之前的第一个帖子,例如 9:00。然后它会寻找 8:00 之前的第一个帖子,可能是在 7:59,所以你会有两个时间非常接近的帖子。或者如果在 16:00 和 8:00 之间没有帖子,则显示的第一个帖子可能在 7:30,然后下一个帖子,也许在 7:28 也会显示(因为它现在是第一个帖子8) 之前可用。
我的假设是您不太关心确切的间距,而是对稍微“减少”帖子的数量更感兴趣,这应该可以实现并且希望适合您的应用程序。
正如我所说,如果您有特定的想法,我很乐意帮助您完善它。
【讨论】:
以上是关于PHP 按时间排序数组并找到与 X 数字最接近的匹配项的主要内容,如果未能解决你的问题,请参考以下文章