Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
模糊排序在PHP中的实现_Php_Sorting_Date_Fuzzy - Fatal编程技术网

模糊排序在PHP中的实现

模糊排序在PHP中的实现,php,sorting,date,fuzzy,Php,Sorting,Date,Fuzzy,我正在处理来自我的用户的特定请求,我无法“中断” 情况: 我们处理历史数据,这些数据有时具有未知的日期值。例如,我们知道1943年发生了一些事情,但我们不知道确切的时间、日期和月份。有时我们确实有确切的日期。我们处理从到的日期,通常这些日期是链接的,因此当一个事件结束时,另一个事件开始。例如,你可以把这些事件想象成一艘船在海上和港口的日期 示例: 我们有两个记录(在本例中,在一篇文章中我们可以有几十个记录),具有这样的结构 Date From - Date To - Event 01.01.19

我正在处理来自我的用户的特定请求,我无法“中断”

情况:

我们处理历史数据,这些数据有时具有未知的日期值。例如,我们知道1943年发生了一些事情,但我们不知道确切的时间、日期和月份。有时我们确实有确切的日期。我们处理从到的日期,通常这些日期是链接的,因此当一个事件结束时,另一个事件开始。例如,你可以把这些事件想象成一艘船在海上和港口的日期

示例:

我们有两个记录(在本例中,在一篇文章中我们可以有几十个记录),具有这样的结构

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