tableau splice() pour les tableaux associatifs

Disons que j'ai un tableau associatif:

array(
  "color" => "red",
  "taste" => "sweet",
  "season" => "summer"
);

Et je veux y introduire un nouvel élément:

"texture" => "bumpy" 

Derrière le 2ème élément, mais en préservant toutes les clés du tableau:

array(
  "color" => "red",
  "taste" => "sweet",
  "texture" => "bumpy", 
  "season" => "summer"
);

Y a-t-il une fonction pour le faire? array_splice() ne le coupera pas, il peut fonctionner avec des touches numériques seulement.

41
demandé sur aksu 2009-11-23 16:19:15

13 réponses

Je pense que vous devez le faire manuellement:

# Insert at offset 2
$offset = 2;
$newArray = array_slice($oldArray, 0, $offset, true) +
            array('texture' => 'bumpy') +
            array_slice($oldArray, $offset, NULL, true);
93
répondu soulmerge 2009-11-23 13:27:46

Basé sur la réponse de soulmerge, j'ai créé cette fonction pratique:

function array_insert($array,$values,$offset) {
    return array_slice($array, 0, $offset, true) + $values + array_slice($array, $offset, NULL, true);  
}
22
répondu ragulka 2012-06-20 07:42:16

Je déteste battre un vieux problème à mort, il semble que certaines personnes ont déjà trouvé des réponses similaires à la mienne. Mais je voudrais offrir une version que je pense est juste un peu plus approfondie. Cette fonction est conçue pour se sentir et se comporter exactement comme array_splice (), y compris sa valeur de retour et la façon dont elle gère les valeurs invalides ou négatives. La seule différence à cet égard est que lorsque vous définissez un tableau de remplacement (ou une chaîne ou un nombre) et non une longueur, vous êtes autorisé à utiliser une valeur null pour la longueur au lieu d'avoir à passer count($array) comme argument. Il supposera que beaucoup d'un null. 0 est toujours 0.

La seule différence de fonction est bien sûr le paramètre $key value, spécifiant quelle clé dériver une position pour commencer à faire des modifications. Le $ offset a également été laissé, maintenant utilisé comme modificateur pour cette position initiale. Les conflits de clés favoriseront toujours le tableau de remplacement mais déclencheront également un avertissement. Et si l' le paramètre key est null ou vide, la fonction ne regardera que le paramètre offset et se comportera comme array_splice, sauf en conservant les valeurs de clé. Si la clé n'est tout simplement pas trouvée, elle se comportera de la même manière que array_splice lorsqu'on lui donne un décalage qui est au-delà de la longueur du tableau; il l'ajoute à la fin.

/**
 * Remove or replace elements of an associative array by key value.
 * @param Object array $input The input associative array
 * @param string $key The key whose position in the array determines the start of the removed portion.
 * @param int $offset Adjust the start position derived from the key by this value.
 * If the sum is positive, it starts from the beginning of the input array.  If negative, it starts from the far end.
 * @param int $length If length is omitted or null, remove everything from key position to the end of the array.
 * If positive, that many elements will be removed.
 * If negative, then the end of the removed portion will be that many elements from the end of the array.
 * @param mixed $replacement Elements from this array will be inserted at the position of the designated key.
 * @return array  Returns the array of the extracted elements.
 */
function array_splice_assoc(&$input, $key, $offset = 0, $length = null, $replacement = null)
{
    if (!is_array($input)) {
        $trace = debug_backtrace();
        extract($trace[0]);
        trigger_error(
            __FUNCTION__."(): expects parameter 1 to be an array, ".gettype($input)." given from $file on line $line",
            E_USER_WARNING
        );
        return false;
    }
    $offset = (int)$offset;
    $replacement = (array)$replacement;
    $inputLength = count($input);
    if (!is_null($key) && $key !== "") {
        $index = array_search($key, $keys = array_keys($input));
        if ($index === false) {
            $offset = $inputLength;
        }
        $offset += $index;
    }
    $index = array_search($key, $keys = array_keys($input));
    if ($index === false) {
        $offset = $inputLength;
    }
    $offset += $index;
    if ($offset < 0) {
        $offset += $inputLength;
        if ($offset < 0) {
            $offset = 0;
        }
    }
    if (is_null($length)) {
        $length = $inputLength;
    } elseif ($length < 0) {
        $length += $inputLength - $offset;
    }
    $extracted = array_slice($input, $offset, $length, true);
    $start = array_slice($input, 0, $offset, true);
    $end = array_slice($input, $offset + $length, $inputLength, true);
    $remaining = $start + $end;
    if (count($conflict = array_keys(array_intersect_key($remaining, $replacement)))) {
        $trace = debug_backtrace();
        extract($trace[0]);
        trigger_error(
            __FUNCTION__."(): key conflict from $file on line $line",
            E_USER_WARNING
        );
        foreach ($conflict as $key) {
            if (isset($start[$key])) {
                unset($start[$key]);
            } else {
                unset($end[$key]);
            }
        }
    }
    $input = (!empty($replacement)) ? $start + $replacement + $end : $remaining;
    return $extracted;
}

Alors...

$array1 = array(
    "fruit1" => "apple",
    "vegetable1" => "carrot",
    "vegetable2" => "potato",
    "fruit2" => "orange",
    "fruit3" => "banana",
    "fruit4" => "pear"
);

$array2 = array(
    "snack" => "chips",
    "vegetable3" => "green bean",
    "vegetable1" => "corn"
);

$vegetables = array_splice_assoc($array1, "fruit1", 1, -3);
print_r($array1);
print_r($vegetables);

array_splice_assoc($array2, "vegetable3", -1, 1, $vegetables);
print_r($array2);

/* Output is:
Array
(
    [fruit1] => apple
    [fruit2] => orange
    [fruit3] => banana
    [fruit4] => pear
)
Array
(
    [vegetable1] => carrot
    [vegetable2] => potato
)
PHP Warning:  array_splice_assoc(): key conflict from /var/www/php/array_splice_assoc.php on line 97 in /var/www/php/array_splice_assoc.php on line 65
Array
(
    [vegetable1] => carrot
    [vegetable2] => potato
    [vegetable3] => green bean
)
*/

Cela pourrait également être un moyen plus simple de remplacer les clés de tableau individuelles tout en conservant sa position, sans avoir à passer par array_values et array_combine.

$array3 = array(
    "vegetable1" => "carrot",
    "vegetable2" => "potato",
    "vegetable3" => "tomato",
    "vegetable4" => "green bean",
    "vegetable5" => "corn"
);

array_splice_assoc($array3, null, 2, 1, array("fruit1" => $array3['vegetable3']));
print_r($array3);

/* OUTPUT:
Array
(
    [vegetable1] => carrot
    [vegetable2] => potato
    [fruit1] => tomato
    [vegetable4] => green bean
    [vegetable5] => corn
)
*/

Modifier: Je viens de découvrir, apparemment array_merge () ne peut pas vraiment faire la différence entre les clés de tableau associatif qui se trouvent être des nombres, et les clés séquentielles régulières. Fusionner les tableaux en utilisant l'opérateur + au lieu de array_merge() évite ce problème.

6
répondu Claymore 2015-08-24 20:11:05

Je ne suis pas sûr s'il y a une fonction pour cela, mais vous pouvez parcourir votre tableau, stocker l'index et utiliser array_push.

1
répondu Ben 2009-11-23 13:24:08

Eh bien, vous pouvez reconstruire le tableau à partir de zéro. Mais le moyen le plus simple de passer par un tableau associatif dans un ordre particulier est de conserver un tableau d'ordre séparé. Comme ça:

$order=array('color','taste','texture','season');
foreach($order as $key) {
  echo $unordered[$key];
}
1
répondu dnagirl 2009-11-23 13:24:59

Il y a un moyen super simple de le faire que je suis venu avec tonight.It recherchera une clé, l'épissera comme normale et retournera l'élément supprimé comme la fonction normale.

function assoc_splice($source_array, $key_name, $length, $replacement){
    return array_splice($source_array, array_search($key_name, array_keys($source_array)), $length, $replacement);
}
1
répondu Colin Knapp 2014-03-03 02:20:22

Voici une autre façon:

function array_splice_assoc(&$input, $offset, $length = 0, $replacement = array()) {
  $keys = array_keys($input);
  $values = array_values($input);
  array_splice($keys, $offset, $length, array_keys($replacement));
  array_splice($values, $offset, $length, array_values($replacement));
  $input = array_combine($keys, $values);
}
1
répondu David 2014-09-09 09:03:00

Basé sur la solution fournie par ragulka et soulmerge, j'ai créé un slightly different function cela vous permet de spécifier la 'clé' au lieu de offset.

<?php
/**
 * Insert values in a associative array at a given position
 *
 * @param array $array
 *   The array in which you want to insert
 * @param array $values
 *   The key => values you want to insert
 * @param string $pivot
 *   The key position to use as insert position.
 * @param string $position
 *   Where to insert the values relative to given $position.
 *   Allowed values: 'after' - default or 'before'
 *
 * @return array
 *   The resulted array with $values inserted a given position
 */
function array_insert_at_position($array, $values, $pivot, $position = 'after'){
  $offset = 0;
  foreach($array as $key => $value){
    ++$offset;
    if ($key == $pivot){
      break;
    }
  }

  if ($position == 'before'){
    --$offset;
  }

  return
    array_slice($array, 0, $offset, TRUE)
    + $values
    + array_slice($array, $offset, NULL, TRUE)
  ;
}
?>
0
répondu Luxian 2012-11-08 12:35:53

Cela fonctionne comme array_splice, mais conserve les clés du tableau inséré:

    function array_splicek(&$array, $offset, $length, $replacement) {
        if (!is_array($replacement)) {
            $replacement = array($replacement);
        }
        $out = array_slice($array, $offset, $length);
        $array = array_slice($array, 0, $offset, true) + $replacement
            + array_slice($array, $offset + $length, NULL, true);
        return $out;
    }

Vous l'utilisez comme vous le feriez array_splice, mais ajoutez simplement un k à la fin. (la réponse de ragulka est bonne, mais cela facilite l'adaptation du code existant.) Ainsi, par exemple

$a = array("color" => "red", "taste" => "sweet", "season" => "summer");
$b = array("texture" => "bumpy");

Au Lieu de

array_splice($a, 2, 0, $b);

Utiliser

array_splicek($a, 2, 0, $b);

, Puis $a contiendra le résultat que vous recherchez.

0
répondu JohnK 2014-07-25 22:52:42

Ma solution imite array_splice exactement, le deuxième paramètre est maintenant String $key, au lieu de Int $offset,

function array_splice_assoc ( &$input ,$key, $length = 0 , $replacement = null ){

    $keys = array_keys( $input );
    $offset = array_search( $key, $keys );

    if($replacement){
        $values = array_values($input);
        $extracted_elements = array_combine(array_splice($keys, $offset, $length, array_keys($replacement)),array_splice($values, $offset, $length, array_values($replacement)));
        $input = array_combine($keys, $values);
    } else {
        $extracted_elements = array_slice($input, $offset, $length);
    }
    return $extracted_elements;
}

Donc, pour obtenir le résultat dont vous avez besoin, vous feriez

$array = array(
  "color" => "red",
  "taste" => "sweet",
  "season" => "summer"
);
$replacement = array("texture" => "bumpy");


array_splice_assoc ($array ,"season", 0, $replacement);

Sortie

Array
(
    [color] => red
    [taste] => sweet
    [texture] => bumpy
    [season] => summer
)
0
répondu TarranJones 2016-01-07 12:54:35

Remarque Importante:Il ne fonctionnera pas si les clés ne sont pas dans le tableau.

Ma solution est (j'aime utiliser des fonctions de tableau PHP natives);

$startIndex = array_search($firstKey, array_keys($arr);
$endIndex = array_search($secondKey, array_keys($arr));
array_splice($arr, $startIndex, $endIndex - $startIndex);

Il est assez simple et vous pouvez le transformer en une fonction facilement.

0
répondu ag0702 2016-09-07 12:50:55
function insrt_to_offest($targetArr, $toBeEmbed, $indAfter) {
    $ind = array_search($indAfter, array_keys($targetArr));
    $offset = $ind + 1;

    # Insert at offset 2    
    $newArray = array_slice($targetArr, 0, $offset, true) +
    $toBeEmbed +
    array_slice($targetArr, $offset, NULL, true); 

    return $newArray;
}


$features = array(
            "color" => "red",
            "taste" => "sweet",
            "season" => "summer"
          );

print_r($features);

$toBeEmbed = array("texture" => "bumpy");

$newArray = insrt_to_offest($features, $toBeEmbed, 'taste');

print_r($newArray);
0
répondu Numan 2017-11-13 10:33:21

Similaire à la réponse de @Luxian, je suis arrivé à une méthode similaire et l'ai configuré comme array_splice_key. https://gist.github.com/4499117

/**
 * Insert another array into an associative array after the supplied key
 *
 * @param string $key
 *   The key of the array you want to pivot around
 * @param array $source_array
 *   The 'original' source array
 * @param array $insert_array
 *   The 'new' associative array to merge in by the key
 *
 * @return array $modified_array
 *   The resulting merged arrays
 */
function array_splice_after_key( $key, $source_array, $insert_array ) { 
    return array_splice_key( $key, $source_array, $insert_array );
}

/**
 * Insert another array into an associative array before the supplied key
 *
 * @param string $key
 *   The key of the array you want to pivot around
 * @param array $source_array
 *   The 'original' source array
 * @param array $insert_array
 *   The 'new' associative array to merge in by the key
 *
 * @return array $modified_array
 *   The resulting merged arrays
 */
function array_splice_before_key( $key, $source_array, $insert_array ) { 
    return array_splice_key( $key, $source_array, $insert_array, -1 );
} 

/**
 * Insert another array into an associative array around a given key
 *
 * @param string $key
 *   The key of the array you want to pivot around
 * @param array $source_array
 *   The 'original' source array
 * @param array $insert_array
 *   The 'new' associative array to merge in by the key
 * @param int $direction
 *   Where to insert the new array relative to given $position by $key
 *   Allowed values: positive or negative numbers - default is 1 (insert after $key)
 *
 * @return array $modified_array
 *   The resulting merged arrays
 */
function array_splice_key( $key, $source_array, $insert_array, $direction = 1 ){
    $position = array_search( $key, array_keys( $source_array ) ) + $direction;

    // setup the return with the source array
    $modified_array = $source_array;

    if( count($source_array) < $position && $position != 0 ) {
        // push one or more elements onto the end of array
        array_push( $modified_array, $insert_array );
    } else if ( $position < 0 ){
        // prepend one or more elements to the beginning of an array
        array_unshift( $modified_array, $insert_array );
    } else {
        $modified_array = array_slice($source_array, 0, $position, true) +
            $insert_array +
            array_slice($source_array, $position, NULL, true);
    }
    return $modified_array;
}
-1
répondu codearachnid 2013-01-10 03:23:49