2011-10-18 19 views
6

Çok boyutlu bir diziyi başka bir diziyle sıralamaya çalışıyorum ancak şu ana kadar kısa bir süre içinde geldim.
array_multisort sadece gerçek sıralama için çalışıyor gibi görünüyor.PHP - Çok boyutlu diziyi başka bir diziyle sırala

$order = array(2,3,1); 

$data = array(
    array('id' => 1, 'title' => 'whatever'), 
    array('id' => 2, 'title' => 'whatever'), 
    array('id' => 3, 'title' => 'whatever') 
); 

Şimdi benim $order dizide sırasına göre benim $data diziyi sıralamak istiyorum:

Bunları 2 diziler olduğunu varsayalım. Benim dizisi oldukça büyük (

$data = array(
    array('id' => 2, 'title' => 'whatever'), 
    array('id' => 3, 'title' => 'whatever') 
    array('id' => 1, 'title' => 'whatever'), 
); 

ben iç içe bir döngü çalıştırarak bu kolayca başarabilirsiniz, ama bu iyi ölçek olmaz ve diziler:
Bu olmak üzere sonucunu istiyoruz şeydir çok daha fazla alan var).

cevap

4

PHP'de bunun için yerleşik bir işlev yoktur ve bu işlevi kullanarak bunu gerçekleştirecek herhangi bir özel işlev düşünemiyorum. Ancak array_map yeterince basit, imo, o zaman neden onu kullanmıyorsunuz? Örnekte

$sorted = array_map(function($v) use ($data) { 
    return $data[$v - 1]; 
}, $order); 
+0

anonim işlevlerimi şu anki php sürümüyle kullanamıyorum - bu nasıl kullanılmadan çalışır? –

+0

Burada bir soru açtık http://stackoverflow.com/questions/13589707/php-modify-code-to-avoid-anonymous-functions –

0

usort() ile özel bir sıralama kullanmayı deneyebilirsiniz. Bu şekilde, ikinci dizinin sırasını belirlemek için ilk diziyi kullanabilirsiniz.

+0

Usort'a bakmıştım, ancak çok boyutlu dizilerle çalışıp çalışmadığını bilmiyorum. – MegaHit

+0

Bu, bu kadar kullanışlı kılan da budur. Sadece bir dize veya çok boyutlu bir dizi olsun, tüm öğeye erişimi olan bir işlevi tanımlar. Böylece karşılaştırma fonksiyonunda, her bir değer dizisini sıralama dizisinde karşılaştırabilirsiniz. Bunun gibi bir şey: return (array_search ($ a ['id'], $ order)> array_search ($ b ['id'], $ order))? -1: 1; –

4

$ veri dizisindeki kimlikleri ardışık ve 1'den başlayarak numaralandırılmış aşağıda vermek kod bu her zaman böyledir varsayar edilir edilir. Bu durumda, kod çalışmıyor.

$result = array(); 
$index = 0; 
foreach ($order as $position) { 
    $result[$index] = $data[$position - 1]; 
    $index++; 
} 

http://codepad.org/YC8w0yHh size sizin örnek veriler için çalıştığını görebilirsiniz.

<?php 

$data = array(
    array('id' => 1, 'title' => 'whatever'), 
    array('id' => 2, 'title' => 'whatever'), 
    array('id' => 3, 'title' => 'whatever') 
); 

$order = array(2,3,1); 
$order = array_flip($order); 

function cmp($a, $b) 
{ 
    global $order; 

    $posA = $order[$a['id']]; 
    $posB = $order[$b['id']]; 

    if ($posA == $posB) { 
     return 0; 
    } 
    return ($posA < $posB) ? -1 : 1; 
} 

usort($data, 'cmp'); 

var_dump($data); 

kanıt http://codepad.org/Q7EcTSfs bakınız: Yukarıda belirtilen varsayım tutmaz ise

DÜZENLEME, aşağıdaki kod aynı sonucu elde edecektir.

$ order dizisinde array_flip() öğesini çağırmak, konum araması için kullanılabilir. Bu, zaman içinde doğrusal veya O (n) olan karma arama gibidir. Daha iyisini yapamazsın.

+0

Son çözümünüz temelde şekerli iç içe geçmiş bir döngüdür.Bunun iyi bir ölçek olduğunu düşünmüyorum. – MegaHit

+0

@MegaHit cevabımda güncellenmiş kodu gör, bundan daha iyisini yapamazsın. –

0

Böyle yapardım. $ Data dizisiyle birlikte özel bir usort işlevini (arr_sort) kullanırdım.

<?php 
$order = array(2,3,1); 
$data = array(
    array('id' => 1, 'title' => 'whatever'), 
    array('id' => 2, 'title' => 'whatever'), 
    array('id' => 3, 'title' => 'whatever') 
); 
function arr_sort($a,$b){ 
    global $order; 
    foreach ($order as $key => $value) { 
    if ($value==$a['id']) { 
     return 0; 
     break; 
    } 
    if ($value==$b['id']) { 
     return 1; 
     break; 
    } 
    } 
} 
usort($data,'arr_sort'); 
echo "<pre>"; 
print_r($data); 
echo "<pre>"; 
İlgili konular