Сортировать массив на основе чисел и определенного фрагмента текста в строке

1

У меня есть массив, который я получил из каталога с файлами PDF в нем, используя scandir

$array = array(7) { 
    [0]=> string(17) "q150824-spost.pdf" 
    [1]=> string(17) "s150826-spost.pdf" 
    [2]=> string(16) "s150826-spro.pdf" 
    [3]=> string(17) "t150827-spost.pdf" 
    [4]=> string(16) "t150827-spro.pdf" 
    [5]=> string(17) "v150825-spost.pdf" 
    [6]=> string(16) "v150825-spro.pdf" 
}

Мне нужно отсортировать массив по номерам в имени файла (например, 150824 который фактически является датой), который я могу сделать, используя следующее:

usort($array, function($a, $b) {
  return filter_var($a, FILTER_SANITIZE_NUMBER_INT) - filter_var($b, FILTER_SANITIZE_NUMBER_INT);
});

Приведенное выше дает мне массив, отсортированный по номерам (что почти то, что я хочу):

$array = array(7) { 
    [0]=> string(17) "q150824-spost.pdf" 
    [1]=> string(17) "v150825-spost.pdf" 
    [2]=> string(16) "v150825-spro.pdf" 
    [3]=> string(16) "s150826-spro.pdf" 
    [4]=> string(17) "s150826-spost.pdf" 
    [5]=> string(17) "t150827-spost.pdf" 
    [6]=> string(16) "t150827-spro.pdf" 
}

Однако в дополнение к этому я также хотел бы сортировать по алфавиту по spost и spro (текст до .pdf). Я не понимаю, как это сделать?

Если две строки в массиве имеют одинаковые числа/дату (например, 150826), я хочу, чтобы затем отсортировать сначала spost а затем spro.

  • 0
    Посмотрите на array_multisort ,
Теги:
arrays
sorting

2 ответа

1
Лучший ответ

Это должно сработать для вас:

Сначала просто возьмите имя и имя темы из имени файла с помощью preg_match_all() и назначьте его переменным. После этого просто отсортируйте его по теме, если числа равны, в противном случае - номерами.

<?php


    usort($arr, function($a, $b){
        preg_match_all("/^\w(\d+)-(\w+)/", $a, $mA);
        preg_match_all("/^\w(\d+)-(\w+)/", $b, $mB);

        $numberA = $mA[1][0];
        $numberB = $mB[1][0];

        $topicA = $mA[2][0];
        $topicB = $mB[2][0];

        if($numberA == $numberB){
            return strcmp($topicA, $topicB);
        }

        return $numberA > $numberB ? 1 : -1;

    });


    print_r($arr);

?>

вывод:

Array
(
    [0] => q150824-spost.pdf
    [1] => v150825-spost.pdf
    [2] => v150825-spro.pdf
    [3] => s150826-spost.pdf
    [4] => s150826-spro.pdf
    [5] => t150827-spost.pdf
    [6] => t150827-spro.pdf
)
  • 1
    Работает спасибо, узнаю что-то новое!
1

На самом деле вы можете просто сделать следующее

$array =[
    "q150824-spost.pdf",
    "s150826-spost.pdf",
    "s150826-spro.pdf",
    "t150827-spost.pdf",
    "t150827-spro.pdf",
    "v150825-spost.pdf",
    "v150825-spro.pdf",
];

usort($array, function($a, $b) {
    return filter_var($a, FILTER_SANITIZE_NUMBER_INT) - filter_var($b, FILTER_SANITIZE_NUMBER_INT) + (strlen($b) > strlen($a) ? 1 : 0);
});

print_r($array);

Вывод

Array
(
    [0] => q150824-spost.pdf
    [1] => v150825-spost.pdf
    [2] => v150825-spro.pdf
    [3] => s150826-spost.pdf
    [4] => s150826-spro.pdf
    [5] => t150827-spost.pdf
    [6] => t150827-spro.pdf
)

Сначала это сортировка, а затем spro

  • 0
    strlen() ничего не сортирует по алфавиту, только по длине строки, поэтому ZZ все еще стоит перед AAA
  • 0
    Ах, умно, так что вы сортируете по разной длине строки. Спасибо, я ценю вашу помощь. Я принимаю ответ Rizier123, так как он более надежный и получил первый ответ.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню