We have three maps which are ordered by how objects are ranked internally and where each object is globally unique as keyed by their "name". For example, in the first list, MewMew is ranked 1st, Spot 2nd, and Johnny 3rd. Note that MewMew is not ranked in List 3, and Ruby is not ranked in List 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.")
);
The method I would suggest is to create a data structure which will hold the combination of all three lists, keyed by their global key, the "name", and maintains a running aggregate score for each entry. Fortunately, the algorithm that you chose for calculating the aggregate (SUM ( 1 / (60 + i))
is well suited to a running calculation method. Also note that doing this this way allows you to actually expand to an arbitrary number of input lists, not just the three that are given here.
$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);
The $combinedRank
variable contains the calculated aggregate rank by name. Expected values are, given the current formula are:
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
You can write additional code as necessary to sort the results and pull in description information.