PHP çok boyutlu dizi sıralama

5 Cevap php

Şu anda bir mysql sorgusu değerlerini oluşan bir sıralama yöntemi oluşturma.

İşte dizinin kısa bir görünümü bulunuyor:

    Array
    (
        [0] => Array
            (
                ['id'] = 1;
                ['countries'] = 'EN,CH,SP';
            )
        [1] => Array
            (
                ['id'] = 2;
                ['countries'] = 'GE,SP,SV';
            )
    )

Sonra sayısal kimliği değerlere dayalı normal bir usort yapmayı başarmış, ama (bir dizi dize, bu durumda bir ülke kodu içeriyorsa) Doğrusu "ülkeleri" alanın içeriği diziyi sıralamak istiyorum, ve id alanına göre.

Aşağıdaki kod parçası, bunu nasıl benim ilk fikriydi, ama ben bir çalışma işlevi içine dahil nasıl hiçbir fikrim yok:

in_array('EN', explode(",",$a['countries']) );

Bunu nasıl yapardın?

Teşekkürler!


Ben gerçekten ne yazık ki bu ile hiçbir alıyorum.

İşte ben şu an için ne var, ve onun bana vererek hataları şey: uasort() [function.uasort]: Invalid comparison function

function compare($a, $b) {
    global $usercountry;

        if ( in_array($usercountry, $a['countries']) && in_array($usercountry, $a['countries']) ) {
            $return = 0;
        }

        else if (in_array($usercountry, $a['countries'])) {
            $return = 1;
        }

        else {
            $return = -1;
        }

        return $return;


        }

        $array= usort($array, "compare");

Bana onunla gitmek için nasıl bir ipucu verebilir kimse var mı?

5 Cevap

Şahsen ben usort() ile birlikte özel bir (anonim) işlevini kullanabilirsiniz.

EDIT: Re - Yorumlarınız. Umarım bu doğru yolda size koyacağız. Bu işlev hem tek EN olduğunda EN veya ne EN veya düzeltilmiş önceliğe sahip olması elemanları eşit öncelik verir.

usort($array,function ($a, $b) {
    $ac = strpos($a['countries'],'EN');
    $bc = strpos($a['countries'],'EN');
    if (($ac !== false && $bc !== false) || ($ac == false && $bc == false)) {
        return 0;
    }
    elseif ($ac !== false) {
        return 1;
    }
    else {
        return -1;
    }
});

Bu işlev, diğer taraftan, hem EN varsa tek EN varsa yüksek, eşit öncelik veren, ve EN vardır ne varsa bir metin karşılaştırma yapar.

usort($array,function ($a, $b) {
    $ac = strpos($a['countries'],'EN');
    $bc = strpos($a['countries'],'EN');
    if ($ac !== false && $bc !== false)) {
        return 0;
    }
    elseif ($ac !== false) {
        return 1;
    }
    elseif ($bc !== false) {
        return -1;
    }
    else {
        if ($a['countries'] == $b['countries']) {
            return 0;
        }
        elseif($a['countries'] > $b['countries']) {
            return 1;
        }
        else {
            return -1;
        }
    }
});

Yine, umarım bu size kendi ileriye taşımak için yeterli yön verecektir. Eğer herhangi bir sorun yaşıyorsanız, daha fazla yorum göndermekten çekinmeyin ve ben yardım etmek için çalışacağım. Eğer kilo ile birden özelliklerini karşılaştırmak için ipe eğer bir not : Korkak bir anahtar bloğu deneyin, örneğin

$ac = array_flip(explode(',',$a['countries']));
$bc = array_flip(explode(',',$b['countries']));
switch (true) {
    case array_key_exists('EN',$ac) && !array_key_exists('EN',$bc):
        return 1;
    case array_key_exists('DE',$ac) && !array_key_exists('EN',$bc) && !array_key_exists('EN',$bc):
        return 1;
    // and so on
}

More Edits!

Aslında karmaşık sıralama sorunu daha düşünüyordum ve ben aşağıdaki çözüm ile geldi, senin göz için. Bu ülkeler endeksinde görünür anahtar kelimelere göre sayısal sıralaması tanımlamak için izin verir. İşte kod bir örnek de dahil olmak üzere, bir:

Example Array

$array = array(
    array(
        'countries' => 'EN,DE,SP',
    ),
    array(
        'countries' => 'EN,CH,SP',
    ),
    array(
        'countries' => 'DE,SP,CH',
    ),
    array(
        'countries' => 'DE,SV,SP',
    ),
    array(
        'countries' => 'EN,SP,FR',
    ),
    array(
        'countries' => 'DE,FR,CH',
    ),
    array(
        'countries' => 'CH,EN,SP',
    ),

);

Sorting Routine

$rankings = array(
    'EN' => 10,
    'SP' => 8,
    'FR' => 7,
    'DE' => 5,
    'CH' => 3,
    'SV' => 1,
);
usort($array, function (&$a, &$b) use ($rankings) {
    if (isset($a['_score'])) {
        $aScore = $a['_score'];
    }
    else {
        $aScore = 0;
        $aCountries = explode(',',$a['countries']);
        foreach ($aCountries as $country) {
            if (isset($rankings[$country])) {
                $aScore += $rankings[$country];
            }
        }
        $a['_score'] = $aScore;
    }

    if (isset($b['_score'])) {
        $bScore = $b['_score'];
    }
    else {
        $bScore = 0;
        $bCountries = explode(',',$b['countries']);
        foreach ($bCountries as $country) {
            if (isset($rankings[$country])) {
                $bScore += $rankings[$country];
            }
        }
        $b['_score'] = $bScore;
    }
    if ($aScore == $bScore) {
        return 0;
    }
    elseif ($aScore > $bScore) {
        return -1;
    }
    else {
        return 1;
    }
});

Not: Bu kod highest ranking entires karşı the karşıp of the array sıralamak. Eğer davranışı tersine istiyorsanız, bu değiştirin:

    elseif ($aScore > $bScore) {

karşı

    elseif ($aScore < $bScore) {

Note that the greater-than was changed karşı a less-than symbol. Making this change will result in the lowest ranking entries being sorted karşı the karşıp of the array. Hope all this helps!

NOTE ALSO!

This code will make a small change karşı your array, in that it adds the _score element karşı each array. Hopefully this is not a problem, as by skarşıring this value I was literally able karşı increase speed by more than double (.00038-.00041 down karşı .00016-.00018 in my benchmarks). If not, remove the if blocks that retrieve the cached value and let the contents of the else blocks execute every time, except of course for the part which skarşıres the score value.

Bu arada, burada bu sıralama sonra dizinin bir var_export() dökümü:

array (
  0 => array (
    'countries' => 'EN,SP,FR',
    '_score' => 25,
  ),
  1 => array (
    'countries' => 'EN,DE,SP',
    '_score' => 23,
  ),
  2 => array (
    'countries' => 'EN,CH,SP',
    '_score' => 21,
  ),
  3 => array (
    'countries' => 'CH,EN,SP',
    '_score' => 21,
  ),
  4 => array (
    'countries' => 'DE,SP,CH',
    '_score' => 16,
  ),
  5 => array (
    'countries' => 'DE,FR,CH',
    '_score' => 15,
  ),
  6 => array (
    'countries' => 'DE,SV,SP',
    '_score' => 14,
  ),
)

Tadını çıkarın!

Nihayet PHP.net bu harika işlevi bulundu:

        function array_msort($array, $cols)
        {
            $colarr = array();
            foreach ($cols as $col => $order) {
                $colarr[$col] = array();
                foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); }
            }
            $eval = 'array_multisort(';
            foreach ($cols as $col => $order) {
                $eval .= '$colarr[\''.$col.'\'],'.$order.',';
            }
            $eval = substr($eval,0,-1).');';
            eval($eval);
            $ret = array();
            foreach ($colarr as $col => $arr) {
                foreach ($arr as $k => $v) {
                    $k = substr($k,1);
                    if (!isset($ret[$k])) $ret[$k] = $array[$k];
                    $ret[$k][$col] = $array[$k][$col];
                }
            }
            return $ret;

        }

This is how each country looks like: $array['countries'] = in_array($needle, $haystack); }

$array = $array = array_msort($array, array('countries'=>SORT_DESC, 'id'=>SORT_ASC));

Tüm yardım için teşekkür ederiz!

array_mulisort ile deneyiniz.

uasort, bir kullanıcı tanımlı karşılaştırma işlevini nasıl kullanacağınızı görmek için dışarı atın.