지정된 정렬 옵션을 갖춘 둘 이상의 "열"(키)에서 멀티미멘트 배열의 정렬 배열

StackOverflow https://stackoverflow.com/questions/809771

문제

여러 차원의 다차원 배열 배열을 둘 이상의 열에 정렬 할 수 있기를 찾고 있습니다. 더욱 복잡하게하기 위해 키/열 당 특정 정렬 옵션을 설정할 수 있기를 원합니다. DB 쿼리의 결과와 비슷한 점이 있지만 실제로는 하나에서 나오지 않으므로 SQL이 아닌 PHP로 정렬해야합니다.

Array
(
    [0] => Array
        (
            [first_name] => Homer
            [last_name] => Simpson
            [city] => Springfield
            [state] => Unknown
            [zip] => 66735
        )

    [1] => Array
        (
            [first_name] => Patty
            [last_name] => Bouvier
            [city] => Scottsdale
            [state] => Arizona
            [zip] => 85250
        )

    [2] => Array
        (
            [first_name] => Moe
            [last_name] => Szyslak
            [city] => Scottsdale
            [state] => Arizona
            [zip] => 85255
        )

    [3] => Array
        (
            [first_name] => Nick
            [last_name] => Riviera
            [city] => Scottsdale
            [state] => Arizona
            [zip] => 85255
        )

)

DB 쿼리로 수행 할 수있는 것과 비슷한 것을 정렬하고 싶습니다. 아, 때로는 열/키를 숫자로 지정해야합니다.

내가 생각했던 것은 이것과 비슷한 것입니다.

$sortOptions = array( array( 'city', SORT_ASC, SORT_STRING ),
                      array( 'zip', SORT_DESC, SORT_NUMERIC),
                      array( 2, SORT_ASC, SORT_STRING) // 2='last_name'
                    );
$sorter = new MultiSort($data, $sortOptions );
$sortedData = $sorter->getSortedArray() ;
print_r( $jmsSorted);

내가 끝내고 싶은 것은 다음과 같습니다.

Array
(
    [0] => Array
        (
            [first_name] => Nick
            [last_name] => Riviera
            [city] => Scottsdale
            [state] => Arizona
            [zip] => 85255
        )

    [1] => Array
        (
            [first_name] => Moe
            [last_name] => Szyslak
            [city] => Scottsdale
            [state] => Arizona
            [zip] => 85255
        )

    [2] => Array
        (
            [first_name] => Patty
            [last_name] => Bouvier
            [city] => Scottsdale
            [state] => Arizona
            [zip] => 85250
        )

    [3] => Array
        (
            [first_name] => Homer
            [last_name] => Simpson
            [city] => Springfield
            [state] => Unknown
            [zip] => 66735
        )

)

업데이트: 이상적으로는 솔루션이 동적으로 생성 될 것이라고 생각합니다.

array_multisort( $city, SORT_ASC, SORT_STRING, $zip, SORT_DESC, SORT_NUMERIC, $last_name, SORT_ASC, SORT_STRING, $inputArray);

문제는 내가 그 주요 이름을 "하드 코드"를 "하드 코드"하고 싶지 않다는 것입니다. 나는 그에 따라 솔루션을 만들려고 노력했다 예제 #3 데이터베이스 결과 정렬 ~로부터 array_multisort() 결국 사용 된 문서 array_multisort() 그러나 나는 동적으로 구축 된 인수 목록을 사용하는 방법을 찾을 수없는 것 같습니다. array_multisort().

저의 시도는 그 주장을 배열로 "체인"하는 것이 었습니다.

call_user_func_array( 'array_multisort', $functionArgs);

그 결과

Warning: Parameter 2 to array_multisort() expected to be a reference, value given in...
도움이 되었습니까?

해결책 4

다차원 배열을 정렬 할 수 있도록 마침내 정착 한 내용은 다음과 같습니다. 위의 두 가지 대답은 모두 좋지만 유연한 것을 찾고있었습니다.

나는 분명히 "올바른"대답이 있다고 생각하지 않지만 이것이 내 필요에 맞는 것이며 유연합니다.

내에서 볼 수 있듯이 @link 의 의견에서 _usortByMultipleKeys() PHP 매뉴얼의 의견에서 현재 존재하지 않는 것처럼 보였지만 나는 믿습니다. http://www.php.net/manual/en/function.usort.php#104398 원본 주석의 새로운 버전입니다. 나는 그 새로운 제안을 사용하여 탐구하지 않았습니다.

/**
 * Sort the resultSet.
 *
 * Usage: $sortOptions = array(
 *          'section', // Defaults to SORT_ASC
 *          'row' => SORT_DESC,
 *          'retail_price' => SORT_ASC);
 *        $results->sortResults($sortOptions);
 *
 * @param array $sortOptions    An array of sorting instructions
 */
public function sortResults(array $sortOptions)
{
    usort($this->_results, $this->_usortByMultipleKeys($sortOptions));
}


/**
 * Used by sortResults()
 *
 * @link http://www.php.net/manual/en/function.usort.php#103722
 */
protected function _usortByMultipleKeys($key, $direction=SORT_ASC)
{
    $sortFlags = array(SORT_ASC, SORT_DESC);
    if (!in_array($direction, $sortFlags)) {
        throw new InvalidArgumentException('Sort flag only accepts SORT_ASC or SORT_DESC');
    }
    return function($a, $b) use ($key, $direction, $sortFlags) {
        if (!is_array($key)) { //just one key and sort direction
            if (!isset($a->$key) || !isset($b->$key)) {
                throw new Exception('Attempting to sort on non-existent keys');
            }
            if ($a->$key == $b->$key) {
                return 0;
            }
            return ($direction==SORT_ASC xor $a->$key < $b->$key) ? 1 : -1;
        } else { //using multiple keys for sort and sub-sort
            foreach ($key as $subKey => $subAsc) {
                //array can come as 'sort_key'=>SORT_ASC|SORT_DESC or just 'sort_key', so need to detect which
                if (!in_array($subAsc, $sortFlags)) {
                    $subKey = $subAsc;
                    $subAsc = $direction;
                }
                //just like above, except 'continue' in place of return 0
                if (!isset($a->$subKey) || !isset($b->$subKey)) {
                    throw new Exception('Attempting to sort on non-existent keys');
                }
                if ($a->$subKey == $b->$subKey) {
                    continue;
                }
                return ($subAsc==SORT_ASC xor $a->$subKey < $b->$subKey) ? 1 : -1;
            }
            return 0;
        }
    };
}

다른 팁

php 5.3에서 배열의 모든 매개 변수는 호출 할 때 참조해야합니다. array_multisort() ~와 함께 call_user_func_array().

이 함수는 다차원 배열을 정렬하고 올바르게 작동하는 참조 된 매개 변수를 빌드하는 방법을 보여줍니다.

function msort()
{
  $params = func_get_args();
  $array = array_pop($params);

  if (!is_array($array))
    return false;

  $multisort_params = array();
  foreach ($params as $i => $param) 
  {
    if (is_string($param)) 
    {
      ${"param_$i"} = array();
      foreach ($array as $index => $row) 
      {
        ${"param_$i"}[$index] = $row[$param];
      }
    }
    else 
      ${"param_$i"} = $params[$i];

    $multisort_params[] = &${"param_$i"};
  }
  $multisort_params[] = &$array; 

  call_user_func_array("array_multisort", $multisort_params);

  return $array;
}

예시:

$ 데이터는 질문에서 주어진 배열입니다

$sorted_data = msort('city', SORT_ASC, SORT_STRING, 'zip', SORT_DESC, SORT_NUMERIC, $data)

이것은 당신이 설명하는 상황에 효과가 있어야합니다.

usort($arrayToSort, "sortCustom");

function sortCustom($a, $b)
{
    $cityComp = strcmp($a['city'],$b['city']);
    if($cityComp == 0)
    {
        //Cities are equal.  Compare zips.
        $zipComp = strcmp($a['zip'],$b['zip']);
        if($zipComp == 0)
        {
            //Zips are equal.  Compare last names.
            return strcmp($a['last_name'],$b['last_name']);
        }
        else
        {
            //Zips are not equal.  Return the difference.
            return $zipComp;
        }
    }
    else
    {
        //Cities are not equal.  Return the difference.
        return $cityComp;
    }
}

그렇게 한 줄로 응축 할 수 있습니다.

function sortCustom($a, $b)
{
    return ($cityComp = strcmp($a['city'],$b['city']) ? $cityComp : ($zipComp = strcmp($a['zip'],$b['zip']) ? $zipComp : strcmp($a['last_name'],$b['last_name'])));
}

사용자 정의 가능한 정렬 기능을 갖는 한 바퀴를 재창조하고 있습니다. 살펴보십시오 array_multisort() 기능.

사용해 보시고 싶을 수도 있습니다 USORT. 분류기에게 분류하는 방법을 알려주는 기능을 만드는 것입니다. 문서는이를 수행하는 방법에 대한 자세한 정보가 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top