WordPress как на ладони
wordpress jino

PHP usort(): сортировка массива по двум (нескольким) полям (параметрам)

Настраиваю сортировку с помощью usort().

Нужно отсортировать полученные с помощью get_posts() записи по двум полям сразу. Сортировка нужна именно для PHP. Как сортировать данные в базе данных об этом я знаю.

Пример того, что у меня есть и что мне нужно. Есть массив объектов:

Array
(
	[0] => stdClass Object
		(
			[laps] => 25
			[time_ms] => 3143413
		)

	[1] => stdClass Object
		(
			[laps] => 25
			[time_ms] => 3146280
		)

	[2] => stdClass Object
		(
			[laps] => 24
			[time_ms] => 3149972
		)

	[3] => stdClass Object
		(
			[laps] => 24
			[time_ms] => 3162714
		)
)

Нужна функция для usort(), которая отсортирует этот массив по полую laps, а затем по time_ms.

П.С. Задача интересная, поэтому решил что поможете. У самого пока не получается...

7
Danya50 3.2 года назад
  • 2
    Kama4697

    Здравствуйте интересный вопрос. Когда-то сталкивался с такой задачей тоже... Вот код который вам поможет:

    /*
     * Сортировка массива по двум параметрам с помощью usort()
     */
    function _usort_object_by_time_ms($a, $b){
    	// поля по которым сортировать
    	$array = array( 'laps'=>'desc', 'time_ms'=>'asc' );
    
    	$res = 0;
    	foreach( $array as $k=>$v ){
    		if( $a->$k == $b->$k ) continue;
    
    		$res = ( $a->$k < $b->$k ) ? -1 : 1;
    		if( $v=='desc' ) $res= -$res;
    		break;
    	}
    
    	return $res;
    }

    Здесь в $array нужно указать ваши поля по порядку, какое первое и второе. В значениях asc и desc - это порядок сортировки...

    Функция для сортировки массива с объектами

    Функция на основе первого примера, с которой удобно работать.

    Передаете в $array массив объектов (можно массив массивов), указываете в $args параметры сортировки и получаете отсортированный массив объектов.

    ## Сортировка объектов/массивов находящихся в массиве, по указанным полям.
    function sort_nested_arrays( $array, $args = array('votes' => 'desc') ){
    	usort( $array, function( $a, $b ) use ( $args ){
    		$res = 0;
    
    		$a = (object) $a;
    		$b = (object) $b;
    
    		foreach( $args as $k => $v ){
    			if( $a->$k == $b->$k ) continue;
    
    			$res = ( $a->$k < $b->$k ) ? -1 : 1;
    			if( $v=='desc' ) $res= -$res;
    			break;
    		}
    
    		return $res;
    	} );
    
    	return $array;
    }

    Пример:

    $arr = array(
    	array(
    		'laps'    => 25,
    		'time_ms' => 3143413,
    	),
    	array(
    		'laps'    => 24,
    		'time_ms' => 3146280,
    	),
    	(object) array(
    		'laps'    => 23,
    		'time_ms' => 3149972,
    	),
    	(object) array(
    		'laps'    => 25,
    		'time_ms' => 3162714,
    	),
    );
    
    $arr = sort_nested_arrays( $arr, array('laps' => 'desc') );
    
    print_r( $arr );
    
    /* Получим:
    Array
    (
    	[0] => Array
    		(
    			[laps] => 25
    			[time_ms] => 3143413
    		)
    
    	[1] => stdClass Object
    		(
    			[laps] => 25
    			[time_ms] => 3162714
    		)
    
    	[2] => Array
    		(
    			[laps] => 24
    			[time_ms] => 3146280
    		)
    
    	[3] => stdClass Object
    		(
    			[laps] => 23
    			[time_ms] => 3149972
    		)
    
    )
    */

    Еще одни пример сортировки по нескольким полям

    Допустим у нас есть массив:

    Array
    (
    	[0] => 10В
    	[1] => 5Б
    	[2] => 9А
    	[3] => 11А
    	[4] => 10А
    	[5] => 5А
    	[6] => 10Г
    	[7] => 9Б
    )

    Нам нужно отсортировать его, сначала по числу в строке, а затем по букве. Делаем так:

    // сортируем по порядку: числа, потом буквы
    usort( $val, function($a,$b){
    	$res = 0;
    
    	// сравниваем числа
    	$inta=intval($a); $intb=intval($b);
    	if( $inta != $intb ){
    		return ( $inta > $intb ) ? 1 : -1;
    	}
    
    	// сравниваем буквы
    	$var1 = preg_replace('~[0-9]+~', '', $a);
    	$var2 = preg_replace('~[0-9]+~', '', $b);
    	$compare = strcmp( $var1, $var2 ); // А считается меньше Б
    	if( $compare !== 0 ){
    		return ( $compare > 0 ) ? 1 : -1;
    	}
    
    	return $res;
    } );

    Получим:

    Array
    (
    	[0] => 5А
    	[1] => 5Б
    	[2] => 9А
    	[3] => 9Б
    	[4] => 10А
    	[5] => 10В
    	[6] => 10Г
    	[7] => 11А
    )
    Олег 3 месяца назад

    Спасибо тебе добрый человек)

    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Регистрация. Вход.