2010-08-30 12 views
6

I tienen una serie de mi inventario (artículos A & B)¿Cómo redistribuyo una matriz en otra matriz de cierta "forma"? PHP

Artículos A & B se venden como conjuntos de 1 x A & 2 x B.

Los artículos también tienen varias propiedades que don' t afecta cómo se distribuyen en conjuntos.

Por ejemplo:

$inventory=array(
array("A","PINK"), 
array("A","MAUVE"), 
array("A","ORANGE"), 
array("A","GREY"), 
array("B","RED"), 
array("B","BLUE"), 
array("B","YELLOW"), 
array("B","GREEN"), 
array("B","BLACK") 
); 

Quiero redistribuir el inventario de $ matriz para crear conjunto (s) $ tal que

$set[0] => Array 
       (
        [0] => array(A,PINK) 
        [1] => array(B,RED) 
        [2] => array(B,BLUE) 

       ) 

$set[1] => Array 
       (
        [0] => array(A,MAUVE) 
        [1] => array(B,YELLOW) 
        [2] => array(B,GREEN) 

       ) 

$set[2] => Array 
       (
        [0] => array(A,ORANGE) 
        [1] => array(B,BLACK) 
        [2] => NULL 

       ) 

$set[3] => Array 
       (
        [0] => array(A,GREY) 
        [1] => NULL 
        [2] => NULL 

       ) 

Como se puede ver. Los elementos se redistribuyen en el orden en que aparecen en el inventario para crear un conjunto de 1 x A & 2 x B. El color no importa al crear el conjunto. Pero debo ser capaz de descubrir qué color entró después de que se creó la matriz $ set. Los conjuntos se crean hasta que se agota todo el inventario. Donde no existe un elemento de inventario para entrar en un conjunto, se inserta un valor NULL.

¡Gracias de antemano!

Respuesta

1

he asumido que todos A's vienen antes de que todo B's:

$inventory=array(
       array("A","PINK"), 
       array("A","MAUVE"), 
       array("A","ORANGE"), 
       array("A","GREY"), 
       array("B","RED"), 
       array("B","BLUE"), 
       array("B","YELLOW"), 
       array("B","GREEN"), 
       array("B","BLACK") 
       ); 

for($b_start_index = 0;$b_start_index<count($inventory);$b_start_index++) { 
     if($inventory[$b_start_index][0] == 'B') { 
       break; 
     } 
} 

$set = array(); 
for($i=0,$j=$b_start_index;$i!=$b_start_index;$i++,$j+=2) { 
     isset($inventory[$j])?$temp1=$inventory[$j]:$temp1 = null; 
     isset($inventory[$j+1])?$temp2=$inventory[$j+1]:$temp2 = null; 
     $set[] = array($inventory[$i], $temp1, $temp2);                                      
} 
+0

Gracias por la ¡Respuesta rápida! Esto ciertamente funciona. Todavía estoy tratando de descifrarlo (las matrices aún son nuevas para mí), pero por lo que puedo ver, no creo que vaya a ser muy flexible para mi propósito. Los conjuntos no siempre se configurarán como (A, B, B). Entonces necesito poder hacer esto "sobre la marcha". Gracias por su esfuerzo – matt

1

Para hacer más fácil el uso de su matriz, debe hacer que sea algo como esto

$inv['A'] = array(
    'PINK', 
    'MAUVE', 
    'ORANGE', 
    'GREY' 
); 
$inv['B'] = array(
    'RED', 
    'BLUE', 
    'YELLOW', 
    'GREEN', 
    'BLACK' 
); 

esta manera se puede bucle a través de ellos por separado.

$createdSets = $setsRecord = $bTemp = array(); 
$bMarker = 1; 
$aIndex = $bIndex = 0; 

foreach($inv['A'] as $singles){ 
    $bTemp[] = $singles; 
    $setsRecord[$singles][] = $aIndex; 
    for($i=$bIndex; $i < ($bMarker*2); ++$i) { 
     //echo $bIndex.' - '.($bMarker*2).'<br/>'; 
     if(empty($inv['B'][$i])) { 
      $bTemp[] = 'null'; 
     } else { 
      $bTemp[] = $inv['B'][$i]; 
      $setsRecord[$inv['B'][$i]][] = $aIndex; 
     } 
    } 

    $createdSets[] = $bTemp; 
    $bTemp = array(); 
    ++$bMarker; 
    ++$aIndex; 
    $bIndex = $bIndex + 2; 
} 


echo '<pre>'; 
print_r($createdSets); 
print_r($setsRecord); 
echo '</pre>'; 

para convertir su matriz en una matriz asociativa, algo así como esto se puede hacer

<?php 
$inventory=array(
    array("A","PINK"), 
    array("A","MAUVE"), 
    array("A","ORANGE"), 
    array("A","GREY"), 
    array("B","RED"), 
    array("B","BLUE"), 
    array("B","YELLOW"), 
    array("B","GREEN"), 
    array("B","BLACK") 
); 

$inv = array(); 
foreach($inventory as $item){ 
    $inv[$item[0]][] = $item[1]; 
} 
echo '<pre>'; 
print_r($inv); 
echo '</pre>'; 
+0

No había pensado en estructurar la matriz como ha sugerido. Puedo ver cómo sería más fácil trabajar con esto. Su solución funciona, pero confía demasiado en conocer el contenido de las matrices antes de ordenarlas. – matt

+1

@matt: primero debe definir su almacenamiento en detalle; de ​​lo contrario, debe pensar demasiado, genéricamente, para calcular la estructura de su almacén de datos, también conocido como Modelo de negocio; todo lo demás será más eficiente porque el inicio el punto está bien definido. –

1

Tal vez se puede utilizar esta función, en el supuesto de que:

... $inventory ya está ordenada (todos A vienen antes de B)
... $inventory es una matriz numérica que mira al índice cero

// $set is the collection to which the generated sets are appended 
// $inventory is your inventory, see the assumptions above 
// $aCount - the number of A elements in a set 
// $bCount - the number of B elements in a set 
function makeSets(array &$sets, array $inventory, $aCount, $bCount) { 
    // extract $aItems from $inventory and shorten $inventory by $aCount 
    $aItems = array_splice($inventory, 0, $aCount); 
    $bItems = array(); 

    // iterate over $inventory until a B item is found 
    foreach($inventory as $index => $item) { 
     if($item[0] == 'B') { 
      // extract $bItems from $inventory and shorten $inventory by $bCount 
      // break out of foreach loop after that 
      $bItems = array_splice($inventory, $index, $bCount); 
      break; 
     } 
    } 

    // append $aItems and $bItems to $sets, padd this array with null if 
    // less then $aCount + $bCount added 
    $sets[] = array_pad(array_merge($aItems, $bItems), $aCount + $bCount, null); 

    // if there are still values left in $inventory, call 'makeSets' again 
    if(count($inventory) > 0) makeSets($sets, $inventory, $aCount, $bCount); 
} 

$sets = array(); 
makeSets($sets, $inventory, 1, 2); 
print_r($sets); 

Ya que menciona que usted no tiene mucha experiencia con matrices, aquí están los enlaces a la documentación de PHP para las funciones que utilicé en el código anterior:

  • array_splice - Retirar una parte de la matriz y la sustituye por otra cosa
  • array_merge - Combinar una o más matrices
  • array_pad - matriz de asientos a la longitud especificada con un valor
1

Este código ordena el inventario sin ninguna suposición sobre el orden de inventario. Puede especificar el patrón (en $ aPattern) y se obedece el orden. También llena las entradas que faltan con el valor predeterminado dado.

<?php 

# config 
$aInventory=array(
array("A","PINK"), 
array("A","MAUVE"), 
array("A","ORANGE"), 
array("A","GREY"), 
array("B","RED"), 
array("B","BLUE"), 
array("B","YELLOW"), 
array("B","GREEN"), 
array("B","BLACK"), 
array("C","cRED"), 
array("C","cBLUE"), 
array("C","cYELLOW"), 
array("C","cGREEN"), 
array("C","cBLACK") 
); 

$aPattern = array('A','B','A','C'); 

$mDefault = null; 

# preparation 
$aCounter = array_count_values($aPattern); 

$aCurrentCounter = $aCurrentIndex = array_fill_keys(array_unique($aPattern),0); 

$aPositions = array(); 

$aFill = array(); 

foreach ($aPattern as $nPosition=>$sElement){ 

    $aPositions[$sElement] = array_keys($aPattern, $sElement); 

    $aFill[$sElement] = array_fill_keys($aPositions[$sElement], $mDefault); 

} // foreach 




$nTotalLine = count ($aPattern); 

$aResult = array(); 

# main loop 
foreach ($aInventory as $aItem){ 

    $sElement = $aItem[0]; 

    $nNeed = $aCounter[$sElement]; 

    $nHas = $aCurrentCounter[$sElement]; 

    if ($nHas == $nNeed){ 

     $aCurrentIndex[$sElement]++; 

     $aCurrentCounter[$sElement] = 1; 

    } else { 

     $aCurrentCounter[$sElement]++; 

    } // if 

    $nCurrentIndex = $aCurrentIndex[$sElement]; 

    if (!isset($aResult[$nCurrentIndex])){ 

     $aResult[$nCurrentIndex] = array(); 

    } // if 

    $nCurrentPosition = $aPositions[$sElement][$aCurrentCounter[$sElement]-1]; 

    $aResult[$nCurrentIndex][$nCurrentPosition] = $aItem; 

} // foreach 

foreach ($aResult as &$aLine){ 

    if (count($aLine)<$nTotalLine){ 

     foreach ($aPositions as $sElement=>$aElementPositions){ 

      $nCurrentElements = count(array_keys($aLine,$sElement)); 

      if ($aCounter[$sElement] != $nCurrentElements){ 

       $aLine = $aLine + $aFill[$sElement]; 

      } // if 

     } // foreach 

    } // if 

    ksort($aLine); 

    # add empty items here 

} // foreach 

# output 
var_dump($aResult); 
1

solución genérica que requiere que se especifique un patrón de la forma

$pattern = array('A','B','B'); 

La salida será en

$result = array(); 

El código:

// Convert to associative array 
$inv = array(); 
foreach($inventory as $item) 
    $inv[$item[0]][] = $item[1]; 

// Position counters : int -> int 
$count = array_fill(0, count($pattern),0); 
$out = 0; // Number of counters that are "out" == "too far" 
// Progression 
while($out < count($count)) 
{ 
    $elem = array(); 
    // Select and increment corresponding counter 
    foreach($pattern as $i => $pat) 
    { 
     $elem[] = $inv[ $pat ][ $count[$i]++ ]; 
     if($count[$i] == count($inv[$pat])) 
      $out++; 
    } 
    $result[] = $elem; 
} 
Cuestiones relacionadas