PHP:聚合文档列表

时间:2013-07-06 07:58:15

标签: php arrays aggregation ranking scoring

我有3个数组,每个数组都包含一个动态生成的文档列表。 (列表会根据用户搜索的内容而变化)

$list1['documentname']
$list2['documentname']
$list3['documentname']

数组是多维的,包含其他信息,例如描述。

因此,如果我想输出第六个文件的名称和描述,我会写:

echo $list1[5]['documentname'].$newline.$list1[5]['description'];

特定文档可能包含在所有三个列表中,也可能不包含在任何列表中。我想要做的是使用以下公式按文档总分对文档进行排名:

$document_Score = (1/(60+rank_list1)) + (1/(60+rank_list2)) + (1/(60+rank_list3))

我试图想办法这样做,但我无处可去。

如果“记录”在 list1 中排名第1,在 list2 中排名2,在 list3 中排名4 ,如何应用以下公式并将分数加在一起。

$document_Score = (1/(60+1)) + (1/(60+2)) + (1/(60+4)) //score for "**document a**"

我知道我需要根据$list1['documentname'] is equal to $list2['documentname']等来应用代码,但我不知道如何实现它。

修改

以下代码是我尝试过的。如果文档名[$ i]值相同,它会为 list1 中的文档提供正确的分数,为 list2 中的文档分数。

然而,这种方法似乎非常冗长,只解决了一半的问题。似乎我必须在循环内部有许多循环来解决这个问题,这不会非常有效

for ($i=0;$i<count($list1);$i++)
    {
            $newline="<br />";

        $list1_rank[$i] = $i+1;
        $list2_rank[$i]= $i+1;
        $list3_rank[$i]= $i+1;
        $1ist1_score[$i]= (1/(60+$list1_rank[$i]));


            if ($list1[$i]['documentname']== $list2[$i]['documentname'])
            {
                $list_1_and_2score[$i]=$list1_score[$i]+ (1/(60+$list2_rank[$i]));
            }


            if ($list1[$i]['documentname']!= $list2[$i]['documentname'])
            {
                $list2_score[$i]=(1/(60+$list2_rank[$i]));
            }
            //Outputting the scores calculated:
            echo $newline."List 1 Document Name: ".$list1[$i]['documentname'].$newline."List 2 Document Name: ".$list2[$i]['documentname'].$newline."List 1 Score: $list1_score[$i]".$newline."List 2 Score: $list2_score[$i]".$newline."Combined Score: $list_1_and_2score[$i]".$newline;

    }

另一个问题是for循环中的条件,$i<count($list1),假设$ list1是最长的数组,如果$ list3更长,该怎么办?我只是说$ i<count($list1) && $i<count($list2) && $i<count($list2)吗?

欢迎提出任何建议,我将非常感激。

谢谢你们。

1 个答案:

答案 0 :(得分:2)

我们有三个地图,这些地图按对象在内部的排名方式排序,每个对象的全局唯一性由其“名称”键入。例如,在第一个列表中,MewMew排名第1,排名第2,Johnny排名第3。请注意,MewMew未在列表3中排名,而Ruby未在列表1中排名。

$list1 = array
(
    array("name" => "MewMew", "description" => "A golden cat."),
    array("name" => "Spot", "description" => "A playful Dalmation."),
    array("name" => "Johnny", "description" => "A big angel fish.")
);

$list2 = array
(
    array("name" => "Spot", "description" => "A playful Dalmation."),
    array("name" => "MewMew", "description" => "A golden cat."),
    array("name" => "Ruby", "description" => "A beautiful parakeet."),
    array("name" => "Johnny", "description" => "A big angel fish.")
);

$list3 = array
(
    array("name" => "Johnny", "description" => "A big angel fish."),
    array("name" => "Spot", "description" => "A playful Dalmation."),
    array("name" => "Ruby", "description" => "A beautiful parakeet.")
);

我建议的方法是创建一个数据结构,它将保存所有三个列表的组合,由其全局键,“名称”键入,并维护每个条目的运行总分。幸运的是,您为计算聚合(SUM ( 1 / (60 + i))而选择的算法非常适合于运行的计算方法。另请注意,这样做可以让您实际扩展到任意数量的输入列表,而不仅仅是这里给出的三个。

$lists = array($list1, $list2, $list3);
$combinedRank = array();

// We need to process all the input lists.
foreach ($lists as $currentList)
{
    $currentRank = 1; // The first entry is ranked "1".

    // This should perform an in-order traversal of the given list, thus highest
    // ranks will happen first, and the lowest, last:
    foreach ($currentList as $entry)
    {
        if(array_key_exists($entry["name"], $combinedRank))
        {
            // If we've already seen an entry for this name, append the value to the existing combined rank.
            $combinedRank[$entry["name"]] += 1 / (60 + $currentRank);
        }
        else
        {
            // If this the first time we've seen this name, add with initial rank of 1/(60+currentRank).
            $combinedRank[$entry["name"]] = 1 / (60 + $currentRank);
        }

        // Increment the currentRank so that later entries have lower ranks.
        $currentRank++;
    }
}

print_r($combinedRank);

$combinedRank变量包含按名称计算的汇总排名。考虑到目前的公式,预期值是:

Spot   = (1 / (60 + 2)) + (1 / (60 + 1)) + (1 / (60 + 2)) ~= 0.0487
Johnny = (1 / (60 + 3)) + (1 / (60 + 4)) + (1 / (60 + 1)) ~= 0.0479
MewMew = (1 / (60 + 1)) + (1 / (60 + 2)) + 0              ~= 0.0325
Ruby   = 0 + (1 / (60 + 3)) + (1 / (60 + 3))              ~= 0.0317

您可以根据需要编写其他代码来对结果进行排序并提取描述信息。