Laravel排序集合并按键排序

27
我正在为我的用户制作排名系统,这是我目前的进展:
获取所有用户并按照他们的分数排序——它可以正常工作。
$users = User::all();
$users = $users->sortByDesc(function($item){
    return $item->points()->sum('amount');
});

找到你在排名中的位置 - 它运行良好

$position = 0;
foreach($users as $user){
    if(Auth::user()->id == $user->id) break;
    $position++;
}

获取我和上/下方的用户 - 不起作用。我得到了随机的用户。看起来集合不再排序了。

$myRank = new Collection();
if($position > 9){
    $myRank->add($users->get($position-1));
    $myRank->add($users->get($position));
    $myRank->add($users->get($position+1));
    return view('rank.show', ['topTen' => $users->take(15), 'myRank' => $myRank]);
}
请帮我解决这个问题,或者提供另一种方法的提示(对于大量记录来说较轻) 。
4个回答

35

我认为问题出在这里:

当您调用User::all()时,您会得到类似于以下内容:

0 => points: 10
1 => points: 50
2 => points: 30
3 => points: 70
4 => points: 20

然后您使用sortBy函数,重新排序集合,但不会重置键。因此,最终您会得到类似以下的结果:

3 => points: 70
1 => points: 50
2 => points: 30
4 => points: 20
0 => points: 10

所以在这里使用位置-1、位置和位置+1是没有意义的。

你可以使用values()函数,它将重置集合的键:

0 => points: 70
1 => points: 50
2 => points: 30
3 => points: 20
4 => points: 10

所以我认为以下代码可以工作。

$users = User::all();
$users = $users->sortByDesc(function($item){
    return $item->points()->sum('amount');
})->values();

然后从位置-1到位置+1获取3个用户:

$myRank = $users->splice($position - 1, 3);

我认为你可以扩展集合类,然后在支持数组上调用ksort。虽然这是非常不好的hack方法。 - Peter Chaula

16

要按键对集合进行排序,可以通过按键对支持数组进行排序,然后重新创建集合。

 $c = collect(['a' => 1, 'c' => 67, 'b' => 2]);
 $items = $c->all();
 ksort($items);

 $c = collect($items);

或者你可以使用一个宏来访问支撑数组。

 Collection::macro('ksort', function(){
    //macros callbacks are bound to collection so we can safely access
    // protected Collection::items
    ksort($this->items);
    
    return $this;
    //to return a new instance
    //return collect($this->items);
 });

如果您需要在代码库中的多个位置按键对集合进行排序,则最后一个解决方案可能非常有用。


12
虽然这个在谷歌上可以看到,但它并不只是为了你的利益。 - Ash
我同意,即使问题对提问者来说不再相关,其他人可能会发现答案有用。此外,两年后可能会出现新的解决方案。 - Dragas
2
在宏中,您错过了ksort($this->items);后面的return $this;。=) - Arash
@ArashMoosapour 返回实例并不是必须的,因为ksort需要引用原始数组。 - Peter Chaula
@peter 当我在集合上使用ksort时,它返回null。 - Arash
1
@ArashMoosapour,我已经做出了修改,返回集合实例。"....... 对集合使用ksort返回null"。你不应该将返回值分配给一个变量。只需调用ksort即可。 - Peter Chaula

2
针对任何需要按照键名排序的数组,我建议使用 PHP 的原生函数 ksort()

1
您只需要使用 sort 集合方法即可:
$c = collect(['a' => 1, 'c' => 67, 'b' => 2]);
$c->sort();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接