我的目标是有选择地过滤出勤列表,按照给定时间段内最早或最晚到达的员工对员工进行排序。我的逻辑是:
现在的问题是,无论使用什么排序算法,相同的出勤率总是带有相同的索引,即最早的总是带有0。对列表进行排序只是将元素直观地推到列表的底部,但它仍然带有0,这使得没有感觉
我原来的代码是
protected function punctualChart ($attendanceCollection, ?string $puncMode) {
$puncMode = $puncMode?? "ear";
// group them into each day. rank by employee with most days
$attendanceDays = $attendanceCollection->groupBy(function ($attendance) {
return $attendance->created_at->format("m-d");
})
->map(function ($daysCollection) use ($puncMode) { // then sum their value for each day? add their indexes. depending on the mode, we know whether highest or lowest is the winner
return $daysCollection->sort(function ($a, $b) use ($puncMode) {
$date1 = $a->created_at;
$date2 = $b->created_at;
if ($puncMode == "lat") {
if ($b > $a) return 1;
if ($a > $b) return -1;
return 0;
}
else {
if ($a > $b) return 1;
if ($b > $a) return -1;
return 0;
}
});
})->values();
// dd($attendanceDays->get(1), $attendanceDays->get(2), $puncMode);
$scoreEmployee = [];
foreach ($attendanceDays as $attendanceCollection) {
foreach ($attendanceCollection as $index => $attendance) {
dump($index);
$employeeId = /*$attendance->employee->last_name.*/$attendance->employee_id;
if (!array_key_exists($employeeId, $scoreEmployee))
$scoreEmployee[$employeeId] = /*0;*/[
"value" => 0,
"model" => $attendance->employee->last_name
];
$scoreEmployee[$employeeId]["value"] += $index+1; // offset 0-based index
}
}
$sortedEmployeeScores = \Illuminate\Support\Arr::sort($scoreEmployee, "value");
dd($scoreEmployee, $sortedEmployeeScores);
return $scoreEmployee;
}
随后被简化为
protected function punctualChart ($attendanceCollection, ?string $puncMode) {
$puncMode = $puncMode?? "ear";
// group them into each day. rank by employee with most days
$attendanceDays = $attendanceCollection->groupBy(function ($attendance) {
return $attendance->created_at->format("m-d");
})
->map(function ($daysCollection) use ($puncMode) { // then sum their value for each day? add their indexes. depending on the mode, we know whether highest or lowest is the winner
return $puncMode == "ear"? $daysCollection->sortBy("created_at"):
$daysCollection->sortByDesc("created_at");
})/*->values()*/;
// dd($attendanceDays->get(1), $attendanceDays->get(2), $puncMode);
$scoreEmployee = [];
foreach ($attendanceDays as $attendanceCollection) {
foreach ($attendanceCollection as $index => $attendance) {
dump($index);
$employeeId = /*$attendance->employee->last_name.*/$attendance->employee_id;
if (!array_key_exists($employeeId, $scoreEmployee))
$scoreEmployee[$employeeId] = /*0;*/[
"value" => 0,
"model" => $attendance->employee->last_name
];
$scoreEmployee[$employeeId]["value"] += $index+1; // offset 0-based index
}
}
$sortedEmployeeScores = \Illuminate\Support\Arr::sort($scoreEmployee, "value");
dd($scoreEmployee, $sortedEmployeeScores);
return $scoreEmployee;
}
从那里我意识到排序是不必要的。有趣的是,结果是自动排序的。但是,该索引是固定的并且无法更改。无论情况如何,相同的元素始终具有相同的索引。所以我想也许,反转列表会有所帮助,即我不会传递
puncMode
,而是反转数组以获得逆数组。但这也行不通
那么我做错了什么以及如何交换他们的索引以反映他们的位置?然后将这个位置求和以在我的图表上渲染(您不需要添加这部分。只是为了完成而显示)?
问题似乎在于您在考勤集合迭代期间如何处理索引。通过 foreach 循环获得的索引对应于原始集合中元素的位置,不一定反映排序后您期望的顺序。
您可以应用的解决方案是在排序后重新分配索引,以便它们反映每个考勤的新位置。这里有一个简单的修复方法:
对出勤进行分组和排序后,将索引重新分配给结果集合。确保索引反映新顺序,无论是按最早还是最晚排序。