2015-04-15 13 views
5

Robię układ zgrabiania dla moich użytkowników i oto co mam do tej pory:laravel sortowania kolekcji, a następnie przez kluczowego

Uzyskaj wszystkich użytkowników i sortować je według punktów - to działa dobrze.

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

Znajdź swoją pozycję w rankingu - to działa dobrze

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

Get sobie i użytkownikom powyżej/poniżej mnie - to nie działa. Dostaję losowych użytkowników. Wygląda na to, że kolekcja nie jest już posortowana.

$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]); 
} 

Proszę mi pomóc z tym jednym albo dać jakąś wskazówkę na innym podejściu (waga dla wielu rekordów)

Odpowiedz

10

Myślę, że problem jest taki:

Po wywołaniu User::all() można dostać coś takiego to:

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

Następnie używasz funkcji sortBy, która zmienia kolejność kolekcji, ale nie resetuje klawiszy. Więc kończy się coś takiego:

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

Stosowanie pozycji -1, pozycji i pozycji +1 nie ma sensu.

Co można zrobić to za pomocą funkcji(), która kasuje klucze ci kolekcji wartości:

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

Więc myślę, że następujący kod będzie działać.

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

A potem dostać 3 użytkowników ze stanowisk - 1 do pozycji + 1:

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

myślę, że można rozszerzyć klasę kolekcja następnie wywołać ksort na tablicy podkładowej . Bardzo brudny hack choć – peter

0

Dla każdego sortowania array przez key, chciałbym zaproponować rodzimych PHP functionksort().

5

Aby posortować według klucza, można uzyskać tablicę podkładową, a następnie ponownie utworzyć kolekcję.

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

$c = collect($items); 

Lub możesz użyć makra, aby uzyskać dostęp do tablicy podkładu.

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

    return $this; 
}); 

Ostatnim rozwiązaniem może być bardzo przydatne, jeśli będzie trzeba uporządkować zbiory, których autorem jest kluczem w wielu miejscach w swojej bazie kodu

+0

To pytanie zostało już wysłane. Dwa lata temu. – zarcel

+8

@zarcel, gdy pojawia się w Google, nie jest to tylko dla twojej korzyści. – ash

+0

Zgadzam się, nawet jeśli pytanie nie dotyczy już pytającego, ktoś inny może uznać te odpowiedzi za przydatne. Ponadto za dwa lata mogą pojawić się nowe rozwiązania. – Dragas

Powiązane problemy