Сортировка мультитусклого массива: расположите по приоритетам, если столбец содержит подстроку, то закажите вторым столбцом

Я в настоящее время создаю метод сортировки, который состоит из значений от запроса mysql.

Вот краткое представление массива:

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

Я преуспел в том, чтобы делать нормальный usort на основе числовых значений идентификаторов, но я скорее хочу отсортировать массив по содержанию поля "стран" (если это содержит строку набора, код страны в этом случае), и затем идентификационным полем.

Следующий отрывок был моей первой идеей того, как сделать это, но я понятия не имею о том, как включить его в рабочую функцию:

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

Как Вы сделали бы это?

Спасибо!


Я действительно нигде не добираюсь с этим, к сожалению.

Вот то, что я имею в настоящий момент, и его предоставление меня только ошибки: 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");

Есть ли кто-либо, кто мог бы дать мне подсказку того, как продолжать ее?

5
задан mickmackusa 29 May 2019 в 23:25
поделиться

5 ответов

SystemTap предназначен для решения такого же проблем, как DTRace, и имеет аналогичный пользовательский интерфейс - пользователь пишет небольшие сценарии, которые прикрепляют действия к именованным зондам.

Говорят, что он нестабилен, он обычно не скомпилирован в ваше ядро ​​по умолчанию, но как только я получил его, у меня не было проблем.

Вы можете посмотреть, как он сравнивается с DTRace в в этой таблице на веб-сайте SystemTap (может быть PartiSan: -)

DTRace была частично портирована в Linux от Paul Fox, энтузиаста, и является Доступно для загрузки для вас, чтобы попробовать - ознакомьтесь с ссылками на своем блоге .

Было сказано, что KPROBES - замена DTRace, но я никогда не пробовал их.

-121--1193215-

Лично я бы использовал пользовательскую (анонимную) функцию в сочетании с USORT () .

Редактировать: RE - ваш комментарий. Надеюсь, это поместит вас на правильный путь. Эта функция дает равный приоритет элементам, которые оба имеют EN или не имеют EN, либо настраивают приоритет, когда только один имеет EN.

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

Эта функция, с другой стороны, дает равный приоритет, если оба имеют EN, выше, если у кого-то есть EN, и имеет значение текста, если не имеет значения.

usort($array,function ($a, $b) {
    $ac = strpos($a['countries'],'EN');
    $bc = strpos($b['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;
        }
    }
});

Опять же, надеюсь, это даст вам достаточно направления, чтобы двигаться вперед самостоятельно. Если у вас возникнут какие-либо проблемы, не стесняйтесь размещать больше комментариев, и я постараюсь помочь. Примечание Если вы связываете, чтобы сравнить несколько свойств с весом: попробуйте блок Funky Switch, например,

$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
}

Больше редактирования!

На самом деле я больше думал о проблеме сложной сортировки, и я придумал следующее решение для рассмотрения. Это позволит вам определить численные рейтинги на основе ключевых слов, которые появятся в индексе стран. Вот код, в том числе пример:

Пример массива

$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',
    ),

);

Проценна сортировки

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

Примечание. Этот код сортирует высочайший рейтинг в верхней части массива . Если вы хотите обратное поведение, измените это:

    elseif ($aScore > $bScore) {

на

    elseif ($aScore < $bScore) {

Обратите внимание, что чем больше, чем было изменено на менее чем символ. Создание этого изменения приведет к более низким рейтинговым записям , которые сортируются в верхней части массива . Надеюсь, что все это помогает!

Обратите внимание также!

Этот код внесет небольшое изменение в ваш массив, в том, что он добавляет элемент _SCORE к каждому массиву. Надеемся, что это не проблема, как и хранив это значение, я буквально мог увеличить скорость более чем в дважды (00038-00041 до .00016-00018 в моих тестах). Если нет, удалите , если , если , если блоки, которые извлекают кэшированное значение и позволяют содержимому else блокировать каждый раз, кроме курса для части, которая хранит значение баллов.

Кстати, вот VAR_Export () Дамп массива после его сортировки:

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,
  ),
)

Наслаждайтесь!

12
ответ дан 18 December 2019 в 11:57
поделиться

Наконец-то нашел эту замечательную функцию в PHP.NET :

        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, как каждая страна выглядит: $ Array [«Страны»] = in_array ($ иглы, $ HayStack); }

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

Спасибо всем за вашу помощь!

2
ответ дан 18 December 2019 в 11:57
поделиться

Как объяснялось ранее, это вызвано Cleartype в Internet Explorer - но существует обходной путь, который, по крайней мере, сделает эту проблему допустимой.

$('#navigation').fadeIn(500, function(){
    if ($.browser.msie){this.style.removeAttribute('filter');}
});

Это должно заставить ИС очистить прозрачность и, таким образом, сделать текст нормальным.

Это все еще не красиво, к сожалению.

-121--3465255-

Как указывает Джефф, id ведет себя как attr_protected. Чтобы предотвратить это, необходимо переопределить список защищенных атрибутов по умолчанию. Будьте внимательны в любом месте, где информация об атрибутах может поступать извне. Поле идентификатора защищено по умолчанию по какой-либо причине.

class Post < ActiveRecord::Base

  private

  def attributes_protected_by_default
    []
  end
end

(Протестировано с ActiveRecord 2.3.5)

-121--728388-

Можно рассмотреть массив _ обход и массив _ переход _ рекурсивный и массив _ карта , которые при объединении, возможно, позволят сделать то, что вы хотите сделать.

1
ответ дан 18 December 2019 в 11:57
поделиться

Как объяснялось ранее, это вызвано Cleartype в Internet Explorer - но существует обходной путь, который, по крайней мере, сделает эту проблему допустимой.

$('#navigation').fadeIn(500, function(){
    if ($.browser.msie){this.style.removeAttribute('filter');}
});

Это должно заставить ИС очистить прозрачность и, таким образом, сделать текст нормальным.

Это все еще не красиво, к сожалению.

-121--3465255-

Как указывает Джефф, id ведет себя как attr_protected. Чтобы предотвратить это, необходимо переопределить список защищенных атрибутов по умолчанию. Будьте внимательны в любом месте, где информация об атрибутах может поступать извне. Поле идентификатора защищено по умолчанию по какой-либо причине.

class Post < ActiveRecord::Base

  private

  def attributes_protected_by_default
    []
  end
end

(Протестировано с ActiveRecord 2.3.5)

-121--728388-

Попробуйте использовать массив _ mulisort .

0
ответ дан 18 December 2019 в 11:57
поделиться

Проверьте uasort, чтобы посмотреть, как использовать функцию сравнения, определяемую пользователем.

0
ответ дан 18 December 2019 в 11:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: