简体   繁体   中英

PHP: Help with Sorting Array

How can I sort an associative array by a weight AND type?

Input

array(
    'a'     => array( 'type' => 't1', 'weight' => 1, 'text' => 'text1' ),
    'b'     => array( 'type' => 't1', 'weight' => 3, 'text' => 'text2' ),
    'c'     => array( 'type' => 't2', 'weight' => 5, 'text' => 'text3' ),
    'd'     => array( 'type' => 't1', 'weight' => 2, 'text' => 'text4' ),
    'e'     => array( 'type' => 't2', 'weight' => 4, 'text' => 'text5' ),
    'f'     => array( 'type' => 't2', 'weight' => 4, 'text' => 'text6' )
);

Desired Output

array(
    'a'     => array( 'type' => 't1', 'weight' => 1, 'text' => 'text1' ),
    'd'     => array( 'type' => 't1', 'weight' => 2, 'text' => 'text4' ),
    'b'     => array( 'type' => 't1', 'weight' => 3, 'text' => 'text2' ),
    'e'     => array( 'type' => 't2', 'weight' => 1, 'text' => 'text5' ),
    'f'     => array( 'type' => 't2', 'weight' => 1, 'text' => 'text6' ),
    'c'     => array( 'type' => 't2', 'weight' => 5, 'text' => 'text3' )
);

Type "t2" must appear at end of array, all other types at start.

Weight must be sorted after type.

I am using uasort with a custom compare function, but am struggling. Here is what I have, but it doesn't work:

function my_comparer($a, $b) {
    return ( $a['type'] !== 't2' && $b['type'] === 't2' )
        ? -1
        : $a['weight'] - $b['weight'];
}

Your function doesn't take account of ($a['type']=='t2')

function my_comparer($a, $b) {
    if ( ($a['type']==='t2') && ($b['type']!=='t2')) return -1;
    if ( ($b['type']==='t2') && ($a['type']!=='t2')) return 1;
    return ($a['weight'] - $b['weight']);
}

Try this:

function my_comparer($a, $b) {
    if( $a['type'] == $b['type'] ){
       return $a['weight'] - $b['weight'];
    }else{
       if( $a['type'] > $b['type'] ) return 1;
       else return -1;
    }
}

(warning, this is untested)

Helper function :

function arrayColumnSort(&$array, $directions) {
    // collect columns
    $columnNames = array_keys($directions);
    $columns = array();
    foreach ($array as $row) {
        foreach ($columnNames as $columnName) {
            if (!isset($columns[$columnName])) {
                $columns[$columnName] = array();
            }

            $columns[$columnName][] = isset($row[$columnName]) ? $row[$columnName] : null;
        }
    }

    // build array_multisort params
    $params = array();
    foreach ($directions as $columnName => $direction) {
        $params = array_merge(
            $params,
            array($columns[$columnName]),
            is_array($direction) ? $direction : array($direction)
        );
    }

    $params[] =& $array;

    // sort
    call_user_func_array('array_multisort', $params);
}

Call :

arrayColumnSort($data, array(
  'type' => SORT_ASC,
  'weight' => SORT_ASC,
));

Simpler way would be array_multisort

$data = array(
    'a'     => array( 'type' => 't1', 'weight' => 1, 'text' => 'text1' ),
    'b'     => array( 'type' => 't1', 'weight' => 3, 'text' => 'text2' ),
    'c'     => array( 'type' => 't2', 'weight' => 5, 'text' => 'text3' ),
    'd'     => array( 'type' => 't1', 'weight' => 2, 'text' => 'text4' ),
    'e'     => array( 'type' => 't2', 'weight' => 4, 'text' => 'text5' ),
    'f'     => array( 'type' => 't2', 'weight' => 4, 'text' => 'text6' )
);

// Obtain a list of columns
foreach ($data as $key => $row) {
    $type[$key]  = $row['type'];
    $weight[$key] = $row['weight'];
}
array_multisort($type, SORT_ASC, $weight, SORT_ASC, $data);

Plus this works if you add any number of types you want sorted in the same way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM