Autor Zpráva
jefitto44
Profil
Mám takéto pole
array (size=32)
23 =>
array (size=11)
'matchesWon' => int 6
'matchesLost' => int 10
'totalPlays' => int 16
'pointsScored' => int 154
'pointsConceded' => int 127
'homeWon' => int 4
'homeLost' => int 4
'awayWon' => int 2
'awayLost' => int 6
'touchB' => int 0
'touchA' => int 0
27 =>
array (size=11)
'matchesWon' => int 11
'matchesLost' => int 6
'totalPlays' => int 17
'pointsScored' => int 286
'pointsConceded' => int 134
'homeWon' => int 5
'homeLost' => int 3
'awayWon' => int 6
'awayLost' => int 3
'touchA' => int 0
'touchB' => int 0

Potrebujem ho zoradiť tak, aby hodnota "pointsScored" šla od najvyššej po najnižšiu. Mám na mysli, že celé položky poľa budú závisieť od veľkosť pointsScored, čiže najprv pojde index 27, až tak index 23. Tých položiek je tam samozrejme viac a ja to potrebujem sortnuť tak, aby poinstScored šlo od najväčšieho po najmenšie.

Vie niekto pomôcť?
juriad
Profil
jefitto44:
Použij funkci uasort.

<?php

$data = array (
    23 =>
        array (
            'matchesWon' => 6,
            'matchesLost' => 10,
            'totalPlays' => 16,
            'pointsScored' => 154,
            'pointsConceded' => 127,
            'homeWon' => 4,
            'homeLost' => 4,
            'awayWon' => 2,
            'awayLost' => 6,
            'touchB' => 0,
            'touchA' => 0,
        ),
    27 =>
        array (
            'matchesWon' => 11,
            'matchesLost' => 6,
            'totalPlays' => 17,
            'pointsScored' => 286,
            'pointsConceded' => 134,
            'homeWon' => 5,
            'homeLost' => 3,
            'awayWon' => 6,
            'awayLost' => 3,
            'touchA' => 0,
            'touchB' => 0,
        )
);

uasort($data, function($a, $b) {return $b['pointsScored'] - $a['pointsScored'];});

var_dump($data);
jefitto44
Profil
Dal som presne toto, čo je v exampli na tej stránke a nefunguje.

1. Anonymna funkcia má 2 vstupné parametre. Keď ju volám, nemá žiadne parametre
2. Nikde neuvádzam, podľa ktorej hodnoty poľa to má sortovať.

Som z toho magor a vôbec mi to nefunguje... na stack overflow som sa tiež nič rozumné nedočítal. Možno by bolo lepšie spraviť ten sort už v SQL? Ale to by bolo ešte zložitejšie...
juriad
Profil
jefitto44:
1. ty ji nemáš volat, volá ji funkce uasort. Ta funkce vrací kladné číslo, pokud má prvky prohodit.
2. uvádíš, v té anonymní funkci. Říkáš, že prvky má prohodit, pokud pointsScored druhého je větší než prvního (zapsané aritmeticky)

Tento příklad mi funguje. Ukaž svůj kód, který ti dělá problémy.
Ano, řazení v SQL je obvykle nejlepší nápad; ty jsi však vůbec nezmínil, že data pochází z databáze.
jefitto44
Profil
function cmp($a, $b) {
            if ($a == $b) {
                return 0;
            }
            return ($a < $b) ? -1 : 1;
        }
        uasort($teamMatches, 'cmp');
        var_dump($teamMatches);exit;

Takto to mám a nefunguje mi to. Nerozumiem, čo to sú tie $a a $b parametre... niekde by som tam mal napísať, že pointsScored, alebo niečo také... vieš to plz opraviť? Chyba, ktorú hádže je

uasort() expects parameter 2 to be a valid callback, function 'cmp' not found or invalid function name
juriad
Profil
jefitto44:
Ta chybová hláška znamená, že uasort nevidí funkci cmp. Je definovaná v kontextu, kde je vidět? Není to náhodou metoda nějaké třidy?
Mě totiž následující kód funguje:
<?php

$teamMatches = array(2 => 2, 4 => 4, 1 => 1);

function cmp($a, $b) {
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}
uasort($teamMatches, 'cmp');
var_dump($teamMatches);exit;

Ten komparátor bere jako parametry dva prvky a vrací číslo (kladné, záporné, nula) podle toho, zda jsou (správně, opačně, shodé).
Můj komparátor je jednodušší:
function cmp($a, $b) {
  # $a obsahuje, $b obsahuje -> výsledek
  # 100, 200 -> vrátí kladné číslo (prohodit)
  # 200, 100 -> vrátí záporné číslo (správné pořádí)
  # 100, 100 -> vrátí nulu (prvky jsou shodné / nezáleží na pořadí)
  return $b['pointsScored'] - $a['pointsScored'];
}
Samozřejmě, že bys ho mohl přepsat do ukecaného:
function cmp($a, $b) {
    if ($a['pointsScored'] == $b['pointsScored']) {
        return 0;
    }
    
    # všimni si prohozených znamének - chceš řadit sestupně
    return ($a['pointsScored'] < $b['pointsScored']) ? 1 : -1;
}

$a a $b jsou prvky pole, které řadíš. V případě pole, které jsi uvedl v [#1] jsou to ty vnitřní pole obsahující informace o hráčích (nebo co to vlastně je).

V podstatě to nedělá nic víc než, že se pro každé dva prvky původního pole zeptá, který má být dřív. (Ehm, toto by bylo tupé a pomalé, ale výsledek je stejný.)

Proč nepoužiješ anonymní funkci, jako jsem to udělal já? To máš snad verzi PHP starší než 5.3?
jefitto44
Profil
Mám to v protected function... môže to byť ten problem?
protected function getBlaBla() {
....
$teamMatches = array(2 => 2, 4 => 4, 1 => 1);
 
function cmp($a, $b) {
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}
uasort($teamMatches, 'cmp');
var_dump($teamMatches);exit;
...
}

Nemôže byť klasická function v metode?
juriad
Profil
jefitto44:
Nemôže byť klasická function v metode?
Může, toto funguje. Nejspíš ještě něco zamlčuješ.
<?php

class Test {
    protected function prot() {
        $teamMatches = array(2 => 2, 4 => 4, 1 => 1);

        function cmp($a, $b) {
            if ($a == $b) {
                return 0;
            }
            return ($a < $b) ? -1 : 1;
        }
        uasort($teamMatches, 'cmp');
        var_dump($teamMatches);exit;
    }

    public function call() {
        $this->prot();
    }
}

$t = new Test();
$t->call();

Ale toto si bude stěžovat:
<?php

class Test {
    function cmp($a, $b) {
        if ($a == $b) {
            return 0;
        }
        return ($a < $b) ? -1 : 1;
    }

    protected function prot() {
        $teamMatches = array(2 => 2, 4 => 4, 1 => 1);

        uasort($teamMatches, 'cmp');
        var_dump($teamMatches);exit;
    }

    public function call() {
        $this->prot();
    }
}

$t = new Test();
$t->call();

Řešením je opravit způsob předání reference na cmp (protože to není funkce, ale metoda existujíci v kontextu objektu $this):
uasort($teamMatches, array($this, 'cmp'));
juriad
Profil
Přečti si php.net/manual/en/language.types.callable.php a pojednání o Passing. Tebe se jedná to „ A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.“

V tomto případě je však blbost mít cmp jako metodu; budeš ji snad používat i při jiných řázeních? Jelikož ona sama nezávisí na $this, měla by být alespoň privátní/protected statickou metodou.
jefitto44
Profil
Toto je skopírované tak ako to mám... getTeamStats($parameters) vráti pole ako je uvedené v prvom príspevku (teda 3D pole)

protected function getConferences($parameters)
    {
        $teamMatches = $this->getTeamStats($parameters);
        function cmp($a, $b) {
            if ($a == $b) {
                return 0;
            }
            return ($a < $b) ? -1 : 1;
        }

        uasort($teamMatches, 'cmp');
        var_dump($teamMatches);exit;
A toto hádže tú chybu, čo som písal.

Tu je var dump celého poľa

array (size=32)
27 =>
array (size=11)
'matchesWon' => int 11
'matchesLost' => int 6
'totalPlays' => int 17
'pointsScored' => int 286
'pointsConceded' => int 134
'homeWon' => int 5
'homeLost' => int 3
'awayWon' => int 6
'awayLost' => int 3
'touchA' => int 0
'touchB' => int 0
23 =>
array (size=11)
'matchesWon' => int 6
'matchesLost' => int 10
'totalPlays' => int 16
'pointsScored' => int 154
'pointsConceded' => int 127
'homeWon' => int 4
'homeLost' => int 4
'awayWon' => int 2
'awayLost' => int 6
'touchB' => int 0
'touchA' => int 0
26 =>
array (size=11)
'matchesWon' => int 10
'matchesLost' => int 6
'totalPlays' => int 16
'pointsScored' => int 247
'pointsConceded' => int 94
'homeWon' => int 4
'homeLost' => int 4
'awayWon' => int 6
'awayLost' => int 2
'touchA' => int 0
'touchB' => int 0
Moderátor Alphard: Zkráceno, kompletní výpis dat ničemu nepomůže.
Keeehi
Profil
protected function getConferences($parameters)
    {
        $teamMatches = $this->getTeamStats($parameters);
 
        uasort($teamMatches, function($a, $b) {return $b['pointsScored'] - $a['pointsScored'];});
        var_dump($teamMatches);
    exit;
}

A nebo nám ještě můžeš ukázat SQL. Neřekl bych, že to bude složité.
jefitto44
Profil
ALELUJA! Ďakujem veľmi pekne, máš u mňa pivo ;)


SQL by bolo zložité, ide o to, že tieto hodnoty tam nemám a počítam ich v PHP až po výbere z DB...

Celý mechanizmus vyzerá takto
Query vyberie z DB informácie o jednotlivých zápasoch, ktoré sa hrali v danej season. NAsledovne sa počíta:
team_A=team_B počet zápasov (totalMatches), čiže napočítavam v cykle +1 podľa toho, koľkokrát sa id tímu vyskytuje v team_A(home), alebo team_B(away)
To isté platí pre score, napočítavam skore koľko dal team_A ak team_A je home ten, čo chcem a to isté pre team_B, čiže je to kus zložitejšie... ale v podstate mne šlo len o to sortnutie. Ďakujem veľmi pekne, si king :)
tiso
Profil
jefitto44: to by malo ísť vytiahnuť z databázy rovno.
juriad
Profil
jefitto44:
Vše co jsi popsal jde počítat už v databázi a myslím, že i poměrně jednoduše. Máš-li zájem ukaž jak vypadá tvé databázové schéma; zkusíme vymyslet dotaz, který vrátí záznamy podobně jako je máš v poli v [#1]. Jen prosím vysvětli, co znamená touchA a touchB.
Keeehi
Profil
jefitto44:
ALELUJA! Ďakujem veľmi pekne, máš u mňa pivo ;)
Kdybys nebyl ***** tak to co jsem napsal já ti napsal juriad už ve [#2]. Respektive moje celá práce byla, že jsem to odtamtud zkopíroval a obalil to metodou.

Myslím, že bys měl dávat pozor a pečlivě zkoumat, co ti ostatní radí. Toto vlákno by pak mělo jen dva příspěvky.
jefitto44
Profil
No upravil som si to kus takto
uasort($teamMatches, function($a, $b) {return ($b['matchesWon'] / $b['totalPlays']) - ($a['matchesWon'] / $a['totalPlays']);});

V skutočnosti som pre zjednodušenie trošku luhal. Nepotrebujem to radiť podľa totalPoints, ale podľa winPercentage. Tá sa počíta tak, že sa vezme počet vyhraných matchov a vydelí sa celkovým počtom odhratých matchov. KeĎ to napíšem takto, zoradí mi to naopak, od najmenšieho po najväčší a ani panovi sa to neda zoradiť naopak. T,. nefunguje na to array reverse, ani nepomôže ak dám najpv $b - $a


Teraz na to pozerám a s hrôzou zisťujem, že mi to nezoradilo korektne... z nejakých dôvodov mi to nahádzalo ako prišlo... Vyzerá, že to zoradilo proste len prvé dva indexy a konec


Ktorý *** vymyslel to php? Prečo tam proste nemôže byť funckia array_sort_value($array, $value, $direction) a napísal by som proste array_sort_value($teamStats, "totalScores", "DESC") a bolo by hotovo?
Kcko
Profil
jefitto44:
Ktorý *** vymyslel to php? Prečo tam proste nemôže byť funckia array_sort_value($array, $value, $direction) a napísal by som proste array_sort_value($teamStats, "totalScores", "DESC") a bolo by hotovo?

Někdo mnohem chytřejší než ty, když máš problém zadrátovat funkční kód ... který Ti byl porazen už na začátku topicu, ach jo ...
juriad
Profil
jefitto44:
Nikdo netušil, že chceš porovnávat desetinná čísla.
Viz php.net/manual/en/function.usort.php to velké varování „Returning non-integer values from the comparison function, such as float, will result in an internal cast to integer of the callback's return value. So values such as 0.99 and 0.1 will both be cast to an integer value of 0, which will compare such values as equal.“

Změň ten komparátor na toto. Pak bude počítat jen s celými čísly a vše bude fungovat. A zamysli se, proč je toto ekvivalentní (práci se zlomky a nejmenšími společnými jmenovateli snad zvládáš).
return ($b['matchesWon'] * $a['totalPlays']) - ($a['matchesWon'] * $b['totalPlays']);

Ktorý *** vymyslel to php? Prečo tam proste nemôže byť funckia array_sort_value($array, $value, $direction) a napísal by som proste array_sort_value($teamStats, "totalScores", "DESC") a bolo by hotovo?
Ten, který byl tak chytrý, že věděl, že nemá smysl vytvořit tisíce funkcí, ale raději jednu univerzální. Kdybys chtěl řadit podle těchto procent, očekával bys funkci array_sort_value_ratio($array, $nominator, $denominator, $direction)?
jefitto44
Profil
Ale ja potrebujem počítať len s desatinnými, nakoľko táto hodnota sa bude pohybovať 0-1 (0 ak tím nevyhraje nai jeden zápas a 1 ak vyhraje všetky). Sú to proste percentá 0-100% <=> 0-1 a medzitým, napr. 50% je 0.5 a toto ja potrebujem porovnávať a zoradiť podľa toho
tiso
Profil
jefitto44:„Prečo tam proste nemôže byť funckia array_sort_value($array, $value, $direction)
Môže a dá sa vytvoriť, ako každá iná vlastná funkcia. Ale nemôžeš od PHP chcieť aby malo každú funkciu ktorú potrebuješ.

Ale ja potrebujem počítať len s desatinnými, nakoľko táto hodnota sa bude pohybovať 0-1
A kto ti bráni?
jefitto44
Profil
Bráni mi php manual
„Returning non-integer values from the comparison function, such as float, will result in an internal cast to integer of the callback's return value. So values such as 0.99 and 0.1 will both be cast to an integer value of 0, which will compare such values as equal.“
Keeehi
Profil
jefitto44:
Ach jo, a je to tady zase. Příspěvek [#18] je zase správné řešení. Ale místo toho, aby jsi to zkusil, tak tu budeš psát o tom, že potrebuješ porovnávat desetinná čísla. Což není pravda jak juriad dokázal. Matematika je mocná, tak se ji nauč, budeš ji v životě potřebovat.
Moderátor juriad: Příspěvek jsem průběžně upravoval k doknalosti, nemám mu za zlé, že si třeba nevšiml úpravy.
jefitto44
Profil
Však dobre, ale nebude mi to rátať kraviny? Tam v podstate ide len o porovnanie dvoch čísel, teda teoreticky by to mohlo fungovať?


Takto mi to nefunguje korektne...
team1: totalplays - 19 z toho 13 víťazných = 0,684 ALE 19*13=247
team2: totalplays - 17 z toho 14 víťazných = 0,824 ALE 17*14=238
čiže mi to nezoradí korektne...
juriad
Profil
jefitto44:
Ty ale nenásobíš čísla patřící jednomu záznamu, ale násobíš záznamy křížem. V tom je ten trik.
team1: totalplays - 19 z toho 13 víťazných = 0,684 ALE 13*17=221
team2: totalplays - 17 z toho 14 víťazných = 0,824 ALE 14*19=266 
juriad
Profil
jefitto44:
Chceš-li, klidně si ten komparátor uprav ternárními výrazy, aby vracel -1, 0, 1.
$diff = ...; # nějaký výpočet s desetinnými čísly.
return $diff == 0 ? 0 : ($diff > 0 ? 1 : -1);
Keeehi
Profil
jefitto44:
A co kdyby jsi konečně uznal, že tu jsou lidé, kteří mají zkušenosti* a kterým by jsi mohl věřit, že když ti něco poradí, tak to v 99% případů bude správně.
A ne, krajiny to počítat nebude. Mohl bych ti sepsat i matematický důkaz ale byl bych rád, kdyby jsi mě tím nezatěžoval. Můj čas je drahý a nerad bych ho strávil psaním důkazů který si můžeš napsat sám. Podle tvých webovek máš základku i střední za sebou, tak bys to měl zvládnou. Dokonce jsi studoval na učitele fyziky. Jestli máš problém i s takto základní matematikou tak se nedivím, že jsi zkončil.

* jsi tu dost dlouho na to, abys věděl, kdo tu často dává dobré rady.
jefitto44
Profil
Konečne mi to funguje.
Keeehi, Ďakujem za podceňovanie, posúva ma to vpred :)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0