根据多个规则对对象进行排序


Sorting objects based on multiple rules

我们学校的合唱团每年情人节都要唱情人节歌。唱诗班整天从一个班转到另一个班,为那些从朋友或重要的人那里收到情人节礼物的人唱歌。

我们每年销售大约1000个情人节歌曲。这些需要根据大量的规则进行排序—例如:

  • 没有一堂课能有超过150个情人节。(我们有五组歌手,我们发现从物流上讲,不可能让每组每节课都送出30多张情人节贺卡。)
  • 任何在第0节或第7节课安排有课程的情人节贺卡接收者必须在第0节或第7节课收到情人节贺卡。
  • 在可能的情况下,情人节歌曲最好均匀地分布在一天中,这样就不会出现第三节课150首,第四节课20首的情况。
  • 五组歌手中的每一组都应该在相同的相对区域交货,以尽量减少运输中浪费的时间。

这样的例子不胜枚举。目前,所有1000份情人节礼物都是手工分类的,效率低得离谱。我正在考虑制作一个PHP或JS脚本来自动化这个过程。以下是我的设想:

  1. 在购买情人节礼物时,学生将填写一个Google表单,上面有他们的名字收礼人的名字,以及他们希望收礼人收到他或她的情人节礼物的上课时间

  2. 脚本将逐行从结果电子表格中获取数据,并为每一行创建一个Valentine对象

  3. 对于每个Valentine对象,脚本将查找接收者的时间表,并以对象变量/属性的形式将他或她的时间表作为房间号添加到Valentine对象中(即$period1 = 312表示接收者的第一个period类在312房间)。

    • 在脚本获取数据之前,这部分可能必须在Google电子表格中手工完成,因为我不确定我是否可以访问学校数据库。
  4. 这是我卡住的部分。一旦脚本拥有1000个左右的Valentine对象列表,每个对象都有自己的$sender, $recp, $period0$period7,$prefPeriod值,脚本将以某种方式根据上述规则和每个对象中的数据将每个对象排序到适当的类周期

如果PHP不是最适合这份工作的语言,我愿意听取建议。我最初选择PHP是因为它是我最了解的语言。

如果有任何帮助,我将不胜感激。

TL;DR:我需要根据几个使用对象属性数据的规则将对象分类

看看usort()。它允许您使用任何用户功能进行排序。在该函数中,您可以任意比较对象。在下面的例子中,我比较了它们的性质:property1property2

<?php
$obj1 = new 'StdClass;
$obj2 = new 'StdClass;
$obj3 = new 'StdClass;
$obj1->property1 = '1';
$obj2->property1 = '2';
$obj3->property1 = '2';
$obj1->property2 = '1';
$obj2->property2 = '1';
$obj3->property2 = '2';
$objs = [$obj2, $obj1, $obj3]; //after sorting, it should be obj1, obj2, obj3
//first we sort by property1, then by property2
usort($objs, function($a, $b)
{
    $result = strcmp($a->property1, $b->property1);
    if ($result === 0)
        $result = strcmp($a->property2, $b->property2);
    return $result;
});
print_r($objs);
结果:

Array
(
    [0] => stdClass Object
        (
            [property1] => 1
            [property2] => 1
        )
    [1] => stdClass Object
        (
            [property1] => 2
            [property2] => 1
        )
    [2] => stdClass Object
        (
            [property1] => 2
            [property2] => 2
        )
)

完全排序!

基本上,如果对象相等,您的自定义函数应该返回1,-1或0。strcmp非常适合于此,因为它返回兼容的值。为了按多个属性排序,我们通过比较第一个结果为0来检查两个对象是否具有相同的property1。如果它们相同,我们比较property2。如您所见,这可以很容易地进一步扩展到其他属性。