2011-06-27 19 views
7

Ok, entonces tengo dos arreglos.Ordenamiento PHP ordenado por subconjunto

Uno es un poco más grande de los datos:

Array 
(
    [12] => blah 
    [36] => foo 
    [58] => blah 
    [60] => blah 
    [72] => blah 
    [90] => bar 
) 

El otro es un subconjunto más pequeño de diferentes pero relacionados de datos en un orden diferente, con cada tecla que corresponde a la misma tecla en la matriz más grande:

Array 
(
    [36] => foo data 
    [90] => bar data 
    [12] => blah data 
) 

Ahora, mi pregunta es, ¿cómo obtengo la primera matriz en tal orden para que las teclas en la primera matriz que tienen las teclas correspondientes en la segunda serie aparezcan primero y en el mismo orden que la segunda matriz?

Por lo tanto, como este:

Array 
(
    [36] => foo 
    [90] => bar 
    [12] => blah 
    [58] => blah 
    [60] => blah 
    [72] => blah 
) 
+1

No lo sé, pero +1 para el nombre de usuario ... –

+0

array_sort podría funcionar para usted – Colum

+0

Probablemente tenga que usar ['uksort'] (http://php.net/manual/en/function.uksort.php) pero es un poco difícil sin usar cierres, creo. ¿Qué versión de PHP estás usando? –

Respuesta

1
$array1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5); 
$array2 = array(36 => 1, 60 => 2, 12 => 1); 

# obtaining keys in the order of question  
$result = array_intersect_key($array2, $array1); 

# assign values from original $array1 
foreach($result as $key => &$value) { 
    $value = $array1[$key]; 
} 
unset($value); # kill reference for safety 

# add missing elements from $array1 
$result += $array1; 

var_dump($result); 

Salida:

array(5) { 
    [36]=> 
    int(2) 
    [60]=> 
    int(4) 
    [12]=> 
    int(1) 
    [58]=> 
    int(3) 
    [72]=> 
    int(5) 
} 

Ver Array Operators para la + para las matrices.

2

uso uksort

edit: errores de sintaxis/lógicos fijos señalados por malko. gracias.

$array_to_sort = array 
(
    12 => "blah", 
    36 => "foo", 
    58 => "blah", 
    60 => "blah", 
    72 => "blah", 
    90 => "bar" 
); 

$sorted_array = array(
    36 => "foo data", 
    90 => "bar data", 
    12 => "blah data" 
); 

global $sorted_array_keys; 
$sorted_array_keys = array_keys($sorted_array); 

function cmp($a, $b) 
{ 
    global $sorted_array_keys; 
    $a_in_array = in_array($a, $sorted_array_keys); 
    $b_in_array = in_array($b, $sorted_array_keys); 
    if ($a_in_array && $b_in_array) { 
     return array_search($a, $sorted_array_keys) - array_search($b, $sorted_array_keys); 
    } else if ($a_in_array) { 
     return -1; 
    } else { 
     return 1; 
    } 
} 

uksort ($array_to_sort , cmp); 
print_r($array_to_sort); 

Esto se ubicó en el agradable y limpio, pero terminó bastante feo y poco clara. Ahora me inclino por algunas de las otras respuestas en lugar de la mía.

+0

lo siento por mi voto incorrecto (lo eliminé) sí puede ser una solución, pero debería proporcionar más detalles. – malko

+0

@malko - Acabo de publicar un ejemplo que debería hacer lo que se solicitó. –

+0

@ jacobs, una de las razones por las que esto no funcionará es que la función cmp no conoce $ keys. Vea mi publicación para ver un ejemplo de trabajo con uksort (usando "cierre" y "uso" para que la función de comparación conozca las $ claves) – malko

5

Solución simple de O (n).

$arr1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5); 
$arr2 = array(36 => 1, 60 => 2, 12 => 1); 

$result = array(); 

foreach($arr2 as $key => $value) { 
    $result[$key] = $arr1[$key]; 
    unset($arr1[$key]); 
} 

foreach($arr1 as $key => $value) { 
    $result[$key] = $arr1[$key]; 
} 

var_dump($result); 

Salida:

array(5) { 
    [36]=> 
    int(2) 
    [60]=> 
    int(4) 
    [12]=> 
    int(1) 
    [58]=> 
    int(3) 
    [72]=> 
    int(5) 
} 
+0

Estaba a punto de enviar aproximadamente lo mismo;) – malko

+0

+1 A veces las cosas son más fáciles de lo que parecen :) –

+0

No es necesario valores desarmados y no es necesario copiar todos los elementos duplicados en otro para cada uno. – hakre

2

Aquí hay un ejemplo usando uksort con cierre, que debería ser más eficaz en gran variedad, creo, pero no he hecho ninguna referencia tan ... difícil realidad confirmar sin prueba.

$a = array(
    12 => 'blah' 
    ,36 => 'foo' 
    ,58 => 'blah' 
    ,60 => 'blah' 
    ,72 => 'blah' 
    ,90 => 'bar' 
); 

$b = array(
    36 => 'foo data' 
    ,90 => 'bar data' 
    ,12 => 'blah data' 
); 

$keysPosition = array_flip(array_keys($b)); 
uksort($a,function($a,$b) use ($keysPosition){ 
    if(isset($keysPosition[$a],$keysPosition[$b])){ 
     return $keysPosition[$a]>$keysPosition[$b]?1:-1; 
    }else if(isset($keysPosition[$a])){ 
     return -1; 
    }else if(isset($keysPosition[$b])){ 
     return 1; 
    } 
    return 0; 
}); 

print_r($a); 

resultado:

Array 
(
    [36] => foo 
    [90] => bar 
    [12] => blah 
    [72] => blah 
    [58] => blah 
    [60] => blah 
) 

Si no puede utilizar el cierre (php < 5.3) se puede hacer algo similar usando un mundial, pero no es limpia.

+0

Gracias! Mi cerebro duele menos ahora – herpyderpy

Cuestiones relacionadas