将对象数组减少到 'best 10'
Reduce an array of objects to the 'best 10'
我有一组对象,它们是足球运动员。该数组可以包含从零到数千名玩家的任何内容。我想将它减少到最好的 10。我最初的尝试如下:
while (count($ArrayOfPlayers) > 10) {
$ArrayIndex = 0;
$WorstPlayerIndex = -1;
$WorstPlayerSkill = 9999999999;
foreach ($ArrayOfPlayers as $Player) {
$Skill = $Player->RatingsArray['Skill'];
if ($Skill < $WorstPlayerSkill) {
$WorstPlayerIndex = $ArrayIndex;
$WorstPlayerSkill = $Skill;
}
$ArrayIndex += 1;
}
// Found the worst player in the list, so remove him.
unset($ArrayOfPlayers[$WorstPlayerIndex]);
}
通读了类似的帖子后,我现在知道问题是数组实际上并没有被更改,所以 while 循环一直持续下去(计算机确实锁定了)。
因此,根据其他帖子的建议,我尝试进行如下更正。
while (count($ArrayOfPlayers) > 10) {
$WorstIndexPlayer = 0;
$WorstPlayerSkill = 9999999999;
foreach ($ArrayOfPlayers as $key => &$Player) {
$Skill = $Player->RatingsArray['Skill'];
if ($Skill < $WorstPlayerSkill) {
$WorstIndexPlayer = $key;
$WorstPlayerSkill = $Skill;
}
}
// Found the worst player in the list, so remove him.
unset($ArrayOfPlayers[$WorstIndexPlayer]);
}
你可能会说,我不明白我现在在做什么,也不明白 $key 部分是干什么用的(它只是从其他示例中复制过来的)。它仍然只是挂起 PC。
我该如何更正这个问题,或者是否有更好的方法来实现这一点?
为了响应对数据结构的请求,这里仅转储 2 个玩家以显示他们的排列方式。
Array
(
[0] => Player Object
(
[ID] => 1
[TeamID] => 1
[Name] => Joseph Dorrington
[RatingsArray] => Array
(
[Skill] => 51993
)
)
[1] => Player Object
(
[ID] => 2
[TeamID] => 1
[Name] => Oliver Tillyard
[RatingsArray] => Array
(
[Skill] => 64574
)
)
使用usort
,你可以先根据这个值对数组进行排序,然后,使用array_slice
,取前10个元素:
function cmp($a, $b){
if ($a->RatingsArray['Skill'] == $b->RatingsArray['Skill']) {
return 0;
}
return ($a->RatingsArray['Skill'] > $b->RatingsArray['Skill']) ? -1 : 1;
}
usort($ArrayOfPlayers, "cmp");
$ArrayOfPlayers = array_slice($ArrayOfPlayers, 0, 10);
我在想可能有更简单的方法。
我们按技能水平(降序)排序,然后 "slice" 前 10 个代表最好的方法怎么样?
假设您的结构如下所示:
$arrayOfPlayers = array (size=6)
0 =>
object(stdClass)[1]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 1187
1 =>
object(stdClass)[2]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 44
2 =>
object(stdClass)[3]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 494
3 =>
object(stdClass)[4]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 584
4 =>
object(stdClass)[5]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 730
5 =>
object(stdClass)[6]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 613
...
下面的代码可以为您做到这一点:
// Call our custom usort function
usort($arrayOfPlayers, 'sort_players');
// Slice the array to the best 10. Note array_slice doesn't care if there's less than 10
$best = array_slice($arrayOfPlayers, 0, 10);
// Our custom sorting function
function sort_players($a, $b) {
if ($a->RatingsArray['Skill'] == $b->RatingsArray['Skill']) {
return 0;
}
return ($a->RatingsArray['Skill'] < $b->RatingsArray['Skill']) ? 1: -1;
}
我有一组对象,它们是足球运动员。该数组可以包含从零到数千名玩家的任何内容。我想将它减少到最好的 10。我最初的尝试如下:
while (count($ArrayOfPlayers) > 10) {
$ArrayIndex = 0;
$WorstPlayerIndex = -1;
$WorstPlayerSkill = 9999999999;
foreach ($ArrayOfPlayers as $Player) {
$Skill = $Player->RatingsArray['Skill'];
if ($Skill < $WorstPlayerSkill) {
$WorstPlayerIndex = $ArrayIndex;
$WorstPlayerSkill = $Skill;
}
$ArrayIndex += 1;
}
// Found the worst player in the list, so remove him.
unset($ArrayOfPlayers[$WorstPlayerIndex]);
}
通读了类似的帖子后,我现在知道问题是数组实际上并没有被更改,所以 while 循环一直持续下去(计算机确实锁定了)。
因此,根据其他帖子的建议,我尝试进行如下更正。
while (count($ArrayOfPlayers) > 10) {
$WorstIndexPlayer = 0;
$WorstPlayerSkill = 9999999999;
foreach ($ArrayOfPlayers as $key => &$Player) {
$Skill = $Player->RatingsArray['Skill'];
if ($Skill < $WorstPlayerSkill) {
$WorstIndexPlayer = $key;
$WorstPlayerSkill = $Skill;
}
}
// Found the worst player in the list, so remove him.
unset($ArrayOfPlayers[$WorstIndexPlayer]);
}
你可能会说,我不明白我现在在做什么,也不明白 $key 部分是干什么用的(它只是从其他示例中复制过来的)。它仍然只是挂起 PC。
我该如何更正这个问题,或者是否有更好的方法来实现这一点?
为了响应对数据结构的请求,这里仅转储 2 个玩家以显示他们的排列方式。
Array
(
[0] => Player Object
(
[ID] => 1
[TeamID] => 1
[Name] => Joseph Dorrington
[RatingsArray] => Array
(
[Skill] => 51993
)
)
[1] => Player Object
(
[ID] => 2
[TeamID] => 1
[Name] => Oliver Tillyard
[RatingsArray] => Array
(
[Skill] => 64574
)
)
使用usort
,你可以先根据这个值对数组进行排序,然后,使用array_slice
,取前10个元素:
function cmp($a, $b){
if ($a->RatingsArray['Skill'] == $b->RatingsArray['Skill']) {
return 0;
}
return ($a->RatingsArray['Skill'] > $b->RatingsArray['Skill']) ? -1 : 1;
}
usort($ArrayOfPlayers, "cmp");
$ArrayOfPlayers = array_slice($ArrayOfPlayers, 0, 10);
我在想可能有更简单的方法。
我们按技能水平(降序)排序,然后 "slice" 前 10 个代表最好的方法怎么样?
假设您的结构如下所示:
$arrayOfPlayers = array (size=6)
0 =>
object(stdClass)[1]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 1187
1 =>
object(stdClass)[2]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 44
2 =>
object(stdClass)[3]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 494
3 =>
object(stdClass)[4]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 584
4 =>
object(stdClass)[5]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 730
5 =>
object(stdClass)[6]
public 'RatingsArray' =>
array (size=1)
'Skill' => int 613
...
下面的代码可以为您做到这一点:
// Call our custom usort function
usort($arrayOfPlayers, 'sort_players');
// Slice the array to the best 10. Note array_slice doesn't care if there's less than 10
$best = array_slice($arrayOfPlayers, 0, 10);
// Our custom sorting function
function sort_players($a, $b) {
if ($a->RatingsArray['Skill'] == $b->RatingsArray['Skill']) {
return 0;
}
return ($a->RatingsArray['Skill'] < $b->RatingsArray['Skill']) ? 1: -1;
}