2010-08-30 16 views
6

Ho un array di mio inventario (VOCI A & B)Come ridistribuire un array in un altro array di una certa "forma". PHP

Articoli A & B sono venduti come insiemi di 1 x A x 2 & B.

Gli articoli hanno anche diverse proprietà che don' t influenzare il modo in cui sono distribuiti in insiemi.

Ad esempio:

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

voglio ridistribuire il $ inventario array per creare $ set (s) in modo tale che

$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 

       ) 

Come si può vedere. Gli articoli vengono ridistribuiti nell'ordine in cui appaiono nell'inventario per creare un set di 1 x A & 2 x B. Il colore non ha importanza quando si crea il set. Ma ho bisogno di essere in grado di scoprire di che colore è andato il set dopo che è stato creato l'array $ set. I set vengono creati fino a esaurimento di tutto l'inventario. Quando non esiste un articolo di inventario per entrare in un insieme, viene inserito un valore NULL.

Grazie in anticipo!

risposta

1

ho pensato che tutto A's vengono prima di tutto 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

Grazie per il risposta veloce! Questo sicuramente funziona. Sto ancora cercando di decifrarlo (gli array sono ancora nuovi per me), ma da quello che posso vedere, non penso che sarà molto flessibile per il mio scopo. I set non vengono sempre configurati come (A, B, B). Quindi devo essere in grado di farlo "al volo". Grazie per il vostro impegno – matt

1

Per rendere più facile da usare l'array, si dovrebbe fare qualcosa di simile

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

In questo modo è possibile loop attraverso loro separatamente.

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

Per spegnere l'array in un array associativo, qualcosa di simile a questo può essere fatto

<?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

Non avevo pensato di strutturare l'array come suggerito. Posso vedere come sarebbe più facile lavorare con questo. La tua soluzione funziona, ma dipende troppo dalla conoscenza del contenuto degli array prima dell'ordinamento. – matt

+1

@matt - Dovresti innanzitutto definire lo spazio di archiviazione in dettaglio, altrimenti devi pensare troppo largamente, troppo genericamente, meglio per elaborare la struttura del tuo data store, altrimenti noto come Business Model, dopo tutto sarà più efficiente, perché l'avvio il punto è ben definito. –

1

Forse è possibile utilizzare questa funzione, partendo dal presupposto che:

... $inventory è già ordinato (tutto A prima del B)
... $inventory è un array numerico che fissa l'indice zero

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

Dal momento che lei ha detto che non avete molta esperienza con gli array, ecco i collegamenti alla documentazione di PHP per le funzioni che ho usato nel codice qui sopra:

  • array_splice - Rimuovere una parte del array e sostituirlo con qualcos'altro
  • array_merge - Unire una o più schiere
  • array_pad - Pad array fino alla lunghezza specificata con un valore
1

Questo codice ordina l'inventario senza alcuna ipotesi sull'ordinazione dell'inventario. È possibile specificare il modello (in $ aPattern) e l'ordine è rispettato. Riempie anche le voci mancanti con un determinato valore predefinito.

<?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

soluzione generica che richiede di specificare un modello della forma

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

l'uscita sarà in

$result = array(); 

Il codice:

// 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; 
} 
Problemi correlati