Řazení jednoúrovňového pole rubrika: Programování: PHP
Zdravím,
snažím se setřídit pole podle dvou klíčů, avšak trochu specifickým způsobem a nedaří se mi to.
Máme pole:
$items = [ ['id' => 1, 'afterId' => 0], ['id' => 2, 'afterId' => 0], ['id' => 3, 'afterId' => 0], ['id' => 4, 'afterId' => 1], ['id' => 5, 'afterId' => 2], ['id' => 6, 'afterId' => 3], ];
Potřebuji ho dostat do následujícího stavu:
[ ['id' => 1, 'afterId' => 0], ['id' => 4, 'afterId' => 1], ['id' => 2, 'afterId' => 0], ['id' => 5, 'afterId' => 2], ['id' => 3, 'afterId' => 0], ['id' => 6, 'afterId' => 3] ]
Tedy mám specifikované nějaké IDčka a pak afterId, dle kterého by se to mělo řadit pod jednotlivé ID na první úrovni, né stromově pod klíčem toho ID. tzn:
[ 1 => [...], 2 => [...], ]
je nežádoucí. Nedaří se mi dostat do 100% validního stavu. Pokud například ID = 10 zařadím mezi některé s afterId = 0, tak již algoritmus selže a je to seřazeno nesprávně.
Systém řazení jaký používám:
usort($items, function($a, $b) { if ($a->afterId === $b->afterId) { return $a->id > $b->id; } return $a->id !== $b->afterId; });
Nevím jak to udělat lépe.. Asi už mi jen hrabe z toho, jak nad tím furt přemýšlím.. Nevěděl by někdo, jak to udělat na 100%, případně jaký algoritmus by se na tohle řešení dal použít a nasměroval mě? Možná je vůbec ten návrh "afterId" špatný a je třeba nějaká lepší struktura. Moc této problematice nerozumím, tak bych ocenil každou radu. Děkuji.
Chyba je, že callback funkce usort nevrací číslo (-1,0,1 ; menší,rovno,větší) ale boolean.
Takže při "false" to vyhodnotí jako rovno (intval(false) === 0) a neudělá to, co čekáš. Správně by to mělo být takto:
<code> $items = [ ['id' => 1, 'afterId' => 0], ['id' => 2, 'afterId' => 0], ['id' => 3, 'afterId' => 0], ['id' => 4, 'afterId' => 1], ['id' => 5, 'afterId' => 2], ['id' => 6, 'afterId' => 3], ]; usort($items, function($a, $b) { if ($a['afterId'] === $b['afterId']) { return $a['id'] - $b['id']; } return $a['id'] - $b['afterId']; }); var_export($items); // output array ( 0 => array ( 'id' => 1, 'afterId' => 0, ), 1 => array ( 'id' => 4, 'afterId' => 1, ), 2 => array ( 'id' => 2, 'afterId' => 0, ), 3 => array ( 'id' => 5, 'afterId' => 2, ), 4 => array ( 'id' => 3, 'afterId' => 0, ), 5 => array ( 'id' => 6, 'afterId' => 3, ), )
Komentáře
- Anonym : Děkuji za odpověď, ale po vyzkoušení to funguje úplně stejně jako to mám já s vracení booleanovské hodnoty. Zakopaný pes bude jinde.. :-/ — 2.2.2021
- Fos4 : Vracení false/true pro callback může občas fungovat (ono se to sejde že to dobře dopadne), ale je to chybně. Co jsem si vzal data tak mně to normálně projde a výstup se shoduje se zadáním (celý kód jsem kvůli formátování přidal do mé původní odpovědi). Zkus jestli nemáš chybu někde jinde, tady to sedí - možná jiná data (v případě že $a['id'] se rovná $b['afterId'] může být problém a chtělo vrátit -1/+1) — 2.2.2021
- Anonym : No to funguje, pokud jsou takto seřazeny.. Pokud v budoucnu některý odmažu a přidám další a začne se to míchat, tak to již nefunguje.. Tohle ukázkové pole se tahá z databáze.. Udělat sem to tedy tak, že se pozice zapisuje do databáze už při vytváření a přepočítávají se pozice i ostatních prvků.. Asi mě to mělo napadnout i dříve.. Je to určitě i rychlejší.. Jelikož dané řazení se mělo provádět ještě v rekurzivní funkci .. Je to takový komplikovanější případ :-D .. Ale děkuji za pomoc :-) — 4.2.2021
Pro plný přístup na Devel.cz se prosím přihlaste:
Nebo se přihlaste jménem a heslem:
Komentáře