2010-08-30 2 views
6

J'ai un tableau de mon inventaire (A POINTS & B)Comment redistribuer un tableau dans un autre tableau d'une certaine "forme". PHP

Articles A & B sont vendus comme des ensembles de 1 x 2 x A & B.

Les articles ont également diverses propriétés qui n » t affecter la façon dont ils sont répartis en ensembles.

Par exemple:

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

Je veux redistribuer l'ensemble des stocks de $ pour créer ensemble de $ (s) de telle sorte 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 

       ) 

Comme vous pouvez le voir. Les éléments sont redistribués dans l'ordre dans lequel ils apparaissent dans l'inventaire pour créer un ensemble de 1 x A & 2 x B. La couleur n'a pas d'importance lors de la création de l'ensemble. Mais j'ai besoin de savoir quelle couleur est entrée dans quel ensemble après la création du tableau $ set. Les ensembles sont créés jusqu'à ce que tout l'inventaire soit épuisé. Lorsqu'un article d'inventaire n'existe pas pour entrer dans un ensemble, une valeur NULL est insérée.

Merci d'avance!

Répondre

1

J'ai supposé que tous les A's viennent avant tout 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

Merci pour la réponse rapide! Cela fonctionne certainement. J'essaie toujours de le déchiffrer (les tableaux sont encore nouveaux pour moi), mais d'après ce que je peux voir, je ne pense pas que ça va être très flexible pour mon but. Les ensembles ne vont pas toujours être configurés comme (A, B, B). Donc je dois être capable de faire ça "à la volée". Merci pour vos efforts – matt

1

Pour faciliter l'utilisation de votre tableau, vous devez faire quelque chose comme ça

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

De cette façon, vous pouvez boucle à travers eux séparément.

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

Pour mettre votre tableau dans un tableau associatif, quelque chose comme cela peut être fait

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

Je n'avais pas pensé à structurer le tableau comme vous l'avez suggéré. Je peux voir comment il serait plus facile de travailler avec ça. Votre solution fonctionne, mais repose trop sur la connaissance du contenu des tableaux avant le tri. – matt

+1

@matt - Vous devez d'abord définir votre stockage en détail, sinon vous devez penser trop largement, trop génériquement, mieux structurer votre structure de stockage de données, autrement dit Business Model, tout sera plus efficace après coup, car le démarrage le point est bien défini. –

1

Peut-être que vous pouvez utiliser cette fonction, en supposant que:

... $inventory est déjà trié (tous A viennent avant B)
... $inventory est un tableau numérique fixant l'index zéro

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

Puisque vous avez mentionné que vous n'avez pas beaucoup d'expérience avec les tableaux, voici les liens vers la documentation php pour les fonctions que j'ai utilisé dans le code ci-dessus:

  • array_splice - Retirez une partie de la tableau et le remplacer par quelque chose d'autre
  • array_merge - fusionner un ou plusieurs tableaux
  • array_pad - tableau jusqu'à la longueur spécifiée avec une valeur
1

Ce code trie l'inventaire sans aucune hypothèse sur l'ordre d'inventaire. Vous pouvez spécifier un motif (dans $ aPattern), et l'ordre est obéi. Il remplit également les entrées manquantes avec une valeur par défaut donnée.

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

solution générique qui vous oblige à spécifier un modèle de la forme

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

La sortie sera en

$result = array(); 

Le code:

// 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; 
} 
Questions connexes