模糊排序在PHP中的实现
我正在处理来自我的用户的特定请求,我无法“中断” 情况: 我们处理历史数据,这些数据有时具有未知的日期值。例如,我们知道1943年发生了一些事情,但我们不知道确切的时间、日期和月份。有时我们确实有确切的日期。我们处理从到的日期,通常这些日期是链接的,因此当一个事件结束时,另一个事件开始。例如,你可以把这些事件想象成一艘船在海上和港口的日期 示例: 我们有两个记录(在本例中,在一篇文章中我们可以有几十个记录),具有这样的结构模糊排序在PHP中的实现,php,sorting,date,fuzzy,Php,Sorting,Date,Fuzzy,我正在处理来自我的用户的特定请求,我无法“中断” 情况: 我们处理历史数据,这些数据有时具有未知的日期值。例如,我们知道1943年发生了一些事情,但我们不知道确切的时间、日期和月份。有时我们确实有确切的日期。我们处理从到的日期,通常这些日期是链接的,因此当一个事件结束时,另一个事件开始。例如,你可以把这些事件想象成一艘船在海上和港口的日期 示例: 我们有两个记录(在本例中,在一篇文章中我们可以有几十个记录),具有这样的结构 Date From - Date To - Event 01.01.19
Date From - Date To - Event
01.01.1943 - 01.02.1943 - Event 1
DD.MM.1943 - 01.04.1943 - Event 2
01.04.1943 - DD.11.1943 - Event 3
DD.02.1943 - 28.02.1943 - Event 4
DD和MM保留为“日uknown”和“月uknown”,因此日期的格式保留为DD.MM.YYYY格式,以便进一步处理
问题:
人类的眼睛和大脑可以快速地分辨出有两个相关的事件——一个接一个,因为它看到事件2中的“日期到”等于事件3中的“日期到”,并按照正确的顺序对它们进行排序。但是,当我想在代码中进行排序时,我使用了一些php数组_排序函数(例如,只按dateFrom排序),我会得到这个错误的顺序
Date From - Date To - Event
01.01.1943 - 01.02.1943 - Event 1
01.04.1943 - DD.11.1943 - Event 3
DD.02.1943 - 28.02.1943 - Event 4
DD.MM.1943 - 01.04.1943 - Event 2
由于字母表中“01”在“DD”字符串之前的顺序。预期的正确顺序
Date From - Date To - Event
01.01.1943 - 01.02.1943 - Event 1
DD.02.1943 - 28.02.1943 - Event 4
DD.MM.1943 - 01.04.1943 - Event 2
01.04.1943 - DD.11.1943 - Event 3
有没有一种方法,如何按照人脑的方式来排序?我真的不知道该怎么办
首先,感谢您进行排序,最好将日期保存在内部YYYY-MM-DD,以便1943-04-01低于1943-11-DD。 可能您可以使用隐藏属性进行排序 第二,不清楚如何处理未知数据。我的意思是,你可以将所有未知日期设置为零,但我认为这不是你想要的 比如说
Event 1 :DD.MM.1943 - 01.04.1943
Event 2 :01.04.1943 - DD.11.1943
Event 3 :DD.MM.1943 - DD.12.1943
我认为您可以使用排序日期字段,这并不准确,但可以帮助您进行排序
如果“起始日期”几乎为已知,则排序日期为“起始日期”。
如果有未知零件但日期到已知,则排序日期为日期到-1天
我认为您需要更多的角色,有些部分可能并不总是正确的,但可能有助于您第二次尝试。这将使用新的输入数据提供所需的输出 方法:() 输出:
Date From - Date To - Event
01.01.1943 - 01.02.1943 - Event 1
DD.02.1943 - 28.02.1943 - Event 4
DD.MM.1943 - 01.04.1943 - Event 2
01.04.1943 - DD.11.1943 - Event 3
如果这不符合您对实际项目数据的预期,请使用示例输入来改进您的问题,这将暴露我方法中的错误。@Radek,我有一点改进我的想法,这里是一个算法作为起点。也许它需要进一步的改进,但你可以用你的数据来测试它
<?php
$event[0]['from']='1943-00-00';
$event[0]['to']='1943-04-00';
$event[1]['from']='1943-05-00';
$event[1]['to']='1943-05-14';
$event[2]['from']='1943-06-00';
$event[2]['to']='1943-06-20';
$event[3]['from']='1943-06-00';
$event[3]['to']='1943-06-00';
$event[4]['from']='1943-04-00';
$event[4]['to']='1943-05-13';
$event[5]['from']='1943-05-14';
$event[5]['to']='1943-00-00';
print_r($event);
$dates=array();
foreach($event as $key => $value)
{
$from['date']=$value['from'];
$from['type']=1;
$from['id']=$key;
array_push($dates,$from);
$to['date']=$value['to'];
$to['type']=2;
$to['id']=$key;
array_push($dates,$to);
}
function compare_dates($a, $b)
{
// sort by date
$retval = strcmp($a['date'], $b['date']);
// if date are equal sort my id
if(!$retval) $retval = $a['id'] - $b['id'];
//if also id is equal sort by type
if(!$retval) $retval = $a['type'] - $b['type'];
return $retval;
}
//first sort by date
usort($dates,'compare_dates');
/*
* unspezific dates shoud be more at the beginning than specific dates
* So go from back to begin
*/
function searchEvent($array,$id)
{
$result=false;
foreach( $array as $key => $value)
{
if($value['id'] == $id)
{
$result=$key;
break;
}
}
return $result;
}
print_r($dates);
$newEvent=array();
//go over dates and rebuild events
while(count($dates) > 0 )
{
//on the beginn of array we hve the most unspezific events, so we start on the end
$lastdate=array_pop($dates);
$id=$lastdate['id'];
$type=$lastdate['type'];
if($type == 1)
{
$from=$lastdate['date'];
}
else
{
$to=$lastdate['date'];
}
$otherDateKey=searchEvent($dates, $id);
$otherDate=$dates[$otherDateKey];
array_splice($dates, $otherDateKey,1);
$type=$otherDate['type'];
if($type == 1)
{
$from=$otherDate['date'];
}
else
{
$to=$otherDate['date'];
}
$data['from']=$from;
$data['to']=$to;
array_unshift($newEvent, $data);
}
print_r($newEvent);
我认为不可能做你想做的事。除非您告诉计算机这两个事件属于彼此,以便您可以按日期和日期来链接事件,否则逻辑处理器无法使用任何信息来确定事件的顺序。由于日期未知,因此无法从任何逻辑意义上对其进行排序。您必须按间隔进行排序。我想我可以通过搜索“date from”的值是否在另一个“date to”记录中来找到记录之间的关系,但我不知道从那里开始:在这种情况下如何按间隔进行排序?这里不是按字母和数字排序的情况,如果不找出记录之间的关系,就无法排序。请注意,使用的示例非常简单,但数据可能要复杂得多(因此简单的排序没有帮助)。谢谢,我会考虑这个解决方案(但我想在这里仅仅反转日期格式没有帮助,因为可能有我使用的更复杂的示例,带有多个“DD.MM”日期,然后我们注定要失败:)是的,我认为你应该搜索一些复杂的例子,并尝试猜测日期从,日期到和日期上,上一次和下一次的数据,但我认为你也可以有不能排序的事件!我不得不在这里删除我之前的评论,很遗憾,它不起作用。请尝试我的示例中的两行。您将得到与我在“问题”部分中提到的相同的顺序,并且该结果是不正确的。我正在寻找一些逻辑来对其进行排序,正如“示例”部分中提到的那样。我修改了我的问题,使之更加精确。@Radek我更新了我的答案。如果这仍然不适合你,请给我留言解释这个问题。嗨,谢谢。我已经实现了这个解决方案,并要求用户跟踪结果,因为有太多的变体需要测试。但不管我到目前为止做了什么,都成功了!
<?php
$event[0]['from']='1943-00-00';
$event[0]['to']='1943-04-00';
$event[1]['from']='1943-05-00';
$event[1]['to']='1943-05-14';
$event[2]['from']='1943-06-00';
$event[2]['to']='1943-06-20';
$event[3]['from']='1943-06-00';
$event[3]['to']='1943-06-00';
$event[4]['from']='1943-04-00';
$event[4]['to']='1943-05-13';
$event[5]['from']='1943-05-14';
$event[5]['to']='1943-00-00';
print_r($event);
$dates=array();
foreach($event as $key => $value)
{
$from['date']=$value['from'];
$from['type']=1;
$from['id']=$key;
array_push($dates,$from);
$to['date']=$value['to'];
$to['type']=2;
$to['id']=$key;
array_push($dates,$to);
}
function compare_dates($a, $b)
{
// sort by date
$retval = strcmp($a['date'], $b['date']);
// if date are equal sort my id
if(!$retval) $retval = $a['id'] - $b['id'];
//if also id is equal sort by type
if(!$retval) $retval = $a['type'] - $b['type'];
return $retval;
}
//first sort by date
usort($dates,'compare_dates');
/*
* unspezific dates shoud be more at the beginning than specific dates
* So go from back to begin
*/
function searchEvent($array,$id)
{
$result=false;
foreach( $array as $key => $value)
{
if($value['id'] == $id)
{
$result=$key;
break;
}
}
return $result;
}
print_r($dates);
$newEvent=array();
//go over dates and rebuild events
while(count($dates) > 0 )
{
//on the beginn of array we hve the most unspezific events, so we start on the end
$lastdate=array_pop($dates);
$id=$lastdate['id'];
$type=$lastdate['type'];
if($type == 1)
{
$from=$lastdate['date'];
}
else
{
$to=$lastdate['date'];
}
$otherDateKey=searchEvent($dates, $id);
$otherDate=$dates[$otherDateKey];
array_splice($dates, $otherDateKey,1);
$type=$otherDate['type'];
if($type == 1)
{
$from=$otherDate['date'];
}
else
{
$to=$otherDate['date'];
}
$data['from']=$from;
$data['to']=$to;
array_unshift($newEvent, $data);
}
print_r($newEvent);