More Than One "Sütun" üzerine MultiDiminsional Dizileri Sıralama Dizisi

4 Cevap php

Ben birden fazla sütun üzerinde çok boyutlu diziler bir dizi sıralamak mümkün arıyorum. Daha da karmaşıklaştıran I tuşu / sütun başına belirli bir sıralama seçeneklerini ayarlamak mümkün olmak istiyorum. Ben bir DB sorgu sonucu benzer ne var, ama aslında, biri bu nedenle PHP sıralamak gereğini yerine SQL gelmiyor.

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
        )

)

Ben bir DB sorgu ile yapılabilir ne benzer sıralamak mümkün olmak istiyorum. Oh, ve bazen bir sütun / anahtar sayısına göre belirtilmesi gerekir.

Ne akılda vardı buna benzer bir şey oldu:

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

Ne ile bitirmek istiyorum şudur:

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
        )

)

UPDATE: Ben ideal bir çözüm dinamik oluştururken neden olacağını düşünüyorum

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

Sorun ben orada "hard code" bu önemli isimleri zorunda istemiyorum olmasıdır. I Example #3 Sorting database results array_multisort() documentation that ended up using array_multisort() adlı dayalı bir çözüm oluşturma çalıştı ama ben {[(3 benim dinamik inşa argüman listesini kullanmak için bir yol bulmak gibi olamaz )]}.

Benim girişimi daha sonra bir diziye birlikte "zincir" bu argümanları oldu ve

call_user_func_array( 'array_multisort', $functionArgs);

Bu bir sonuçlanır

Warning: Parameter 2 to array_multisort() expected to be a reference, value given in...

4 Cevap

İşte Sonunda çok boyutlu dizileri sıralamak için güçlü olmak için üzerinde yerleşmiş budur. Yukarıdaki cevaplar Her ikisi de iyi ama ben de esnek bir şey arıyordum.

Ben kesinlikle herhangi bir "doğru" cevabı olduğunu sanmıyorum, ama bu benim ihtiyaçları için neyin işe yaradığını ve esnektir.

Eğer _usortByMultipleKeys() şu anda mevcut görünmüyor PHP kılavuzunda bir açıklama uyarlanan, ama {[(2 inanıyorum edildi Yorumlarınız benim @link gördüğünüz gibi )]} orijinal yorumun yeni bir sürümüdür. Ben bu yeni öneri kullanılarak incelenmiştir değil.

/**
 * 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 dizide her parametre call_user_func_array() ile array_multisort() çağırırken bir referans olmalıdır.

Bu fonksiyon, çok boyutlu bir dizi sıralar ve düzgün çalışır başvurulan params bir dizi oluşturmak için bir yol gösterir.

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

Örnek:

$ Data sorunundan verilen dizidir

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

Bu tarif durum için çalışması gerekir.

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

Sen şöyle bir satır sığdırmaktı olabilir:

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'])));
}

Bildiğim kadarıyla özelleştirilebilir bir sıralama işlevi sahip olarak, siz tekerleği yeniden icat ediyoruz. array_multisort() fonksiyonuna bir göz atın.

Sen usort kullanarak denemek isteyebilirsiniz. Yapmanız gereken tek şey onu sıralamak nasıl sıralayıcıyı anlatmak bir işlevleri olun. Docs bunu nasıl daha fazla bilgi var.