Как добавить значение массива в середину ассоциативного массива? - PullRequest
24 голосов
/ 27 января 2010

Допустим, у меня есть этот массив:

$array = array('a'=>1,'z'=>2,'d'=>4);

Позже в скрипте я хочу добавить значение 'c'=>3 перед 'z'. Как я могу это сделать?

Да, порядок важен. Когда я запускаю foreach () через массив, я НЕ хочу, чтобы это новое добавленное значение добавлялось в конец массива. Я получаю этот массив из mysql_fetch_assoc ()

Ключи, которые я использовал выше, являются заполнителями. Использование ksort () не приведет к тому, что я хочу.

http://www.php.net/manual/en/function.array-splice.php#88896 выполняет то, что я ищу, но я ищу что-то попроще.

Возьмите пример таблицы в БД с примерно 30 столбцами. Я получаю эти данные с помощью mysql_fetch_assoc (). В этом новом массиве после столбца «пицца» и «напиток» я хочу добавить новый столбец «full_dinner», который объединяет значения «пицца» и «напиток», чтобы при запуске foreach () в указанном массиве «full_dinner» идет сразу после «drink»

Ответы [ 13 ]

34 голосов
/ 24 марта 2012

Я что-то упустил?

$key = 'z';
$offset = array_search($key, array_keys($array));

$result = array_merge
        (
            array_slice($array, 0, $offset),
            array('c' => 3),
            array_slice($array, $offset, null)
        );

Обработка несуществующих ключей (по умолчанию добавляется $data):

function insertBeforeKey($array, $key, $data = null)
{
    if (($offset = array_search($key, array_keys($array))) === false) // if the key doesn't exist
    {
        $offset = 0; // should we prepend $array with $data?
        $offset = count($array); // or should we append $array with $data? lets pick this one...
    }

    return array_merge(array_slice($array, 0, $offset), (array) $data, array_slice($array, $offset));
}

Демо:

$array = array('a' => 1, 'z' => 2, 'd' => 4);

// array(4) { ["a"]=> int(1) ["c"]=> int(3) ["z"]=> int(2) ["d"]=> int(4) }
var_dump(insertBeforeKey($array, 'z', array('c' => 3)));

// array(4) { ["a"]=> int(1) ["z"]=> int(2) ["d"]=> int(4) ["c"]=> int(3) }
var_dump(insertBeforeKey($array, 'y', array('c' => 3)));
14 голосов
/ 27 января 2010

Простой подход к этому состоит в том, чтобы перебирать исходный массив, создавая новый по ходу:

function InsertBeforeKey( $originalArray, $originalKey, $insertKey, $insertValue ) {

    $newArray = array();
    $inserted = false;

    foreach( $originalArray as $key => $value ) {

        if( !$inserted && $key === $originalKey ) {
            $newArray[ $insertKey ] = $insertValue;
            $inserted = true;
        }

        $newArray[ $key ] = $value;

    }

    return $newArray;

}

Тогда просто позвоните

$array = InsertBeforeKey( $array, 'd', 'c', 3 );
10 голосов
/ 22 марта 2012

Согласно вашему первоначальному вопросу, лучший ответ, который я могу найти, это:

$a = array('a'=>1,'z'=>2,'d'=>4);

$splitIndex = array_search('z', array_keys($a));
$b = array_merge(
        array_slice($a, 0, $splitIndex), 
        array('c' => 3), 
        array_slice($a, $splitIndex)
);

var_dump($b);
array(4) {
  ["a"]=>
  int(1)
  ["c"]=>
  int(3)
  ["z"]=>
  int(2)
  ["d"]=>
  int(4)
}

В зависимости от размера ваших массивов, вы будете дублировать довольно много данных во внутренней памяти, независимо от того, используете ли вы это решение или другое.

Более того, ваше пятое редактирование, похоже, указывает на то, что в качестве альтернативы ваш SQL-запрос может быть улучшен. То, что вы, похоже, хотите сделать, будет примерно таким:

SELECT a, b, CONCAT(a, ' ', b) AS ab FROM ... WHERE ...

Если изменение вашего оператора SELECT может сделать решение PHP избыточным, вам обязательно следует использовать модифицированный SQL.

5 голосов
/ 27 января 2010
function insertValue($oldArray, $newKey, $newValue, $followingKey) {

    $newArray = array ();
    foreach (array_keys($oldArray) as $k) {
        if ($k == $followingKey)
            $newArray[$newKey] = $newValue;
        $newArray[$k] = $oldArray [$k];
    }

    return $newArray;
}

Вы называете это как

insertValue($array, 'c', '3', 'z')

Что касается редактирования 5:

отредактируйте свой sql так, чтобы он читал

SELECT ..., pizza, drink, pizza+drink as full_meal, ... FROM ....

и у вас автоматически появится столбец:

Array (
  ...
  'pizza' => 12,
  'drink' => 5,
  'full_meal' => 17,
  ...
)
0 голосов
/ 23 июня 2019

Упрощенная функция Alix Axel, если вам нужно просто вставить данные в n-ю позицию:

function array_middle_push( array $array, int $position, array $data ): array {
   return array_merge( array_slice( $array, 0, $position ), $data, array_slice( $array, $position ) );
}
0 голосов
/ 25 октября 2015

Большое использование функций массива, но как об этом проще:

Добавить статический столбец в SQL, а затем заменить его в результирующем массиве.Порядок остается прежним:

SQL:

Select pizza , drink , 'pizza-drink' as 'pizza-drink' , 28 columns..... From Table

Массив:

$result['pizza-drink'] = $result['pizza'] . $result['drink'];
0 голосов
/ 26 марта 2012
function putarrayelement(&$array, $arrayobject, $elementposition, $value = null) {

        $count = 0;
        $return = array();
        foreach ($array as $k => $v) {
        if ($count == $elementposition) {
                if (!$value) {
                    $value = $count;
                }
            $return[$value] = $arrayobject;
            $inserted = true;
        }
        $return[$k] = $v;
        $count++;
        }
        if (!$value) {
           $value = $count;
        }
        if (!$inserted){
            $return[$value];
        }
        $array = $return;
       return $array;
     }

        $array = array('a' => 1, 'z' => 2, 'd' => 4);
        putarrayelement($array, '3', 1, 'c');
        print_r($array);
0 голосов
/ 23 марта 2012

На данный момент лучшее, что я могу найти, чтобы попытаться минимизировать создание новых массивов, - это две функции:

первый пытается заменить значение в исходном массиве, а второй возвращает новый массив.

// replace value into the original array
function insert_key_before_inplace(&$base, $beforeKey, $newKey, $value) {
 $index = 0;
 foreach($base as $key => $val) {
    if ($key==$beforeKey) break;
    $index++;
 }
 $end = array_splice($base, $index, count($base)-$index);
 $base[$newKey] = $value;
 foreach($end as $key => $val) $base[$key] = $val;
}


$array = array('a'=>1,'z'=>2,'d'=>4);

insert_key_before_inplace($array, 'z', 'c', 3);

var_export($array); // array ( 'a' => 1, 'c' => 3, 'z' => 2, 'd' => 4, )

// create new array
function insert_key_before($base, $beforeKey, $newKey, $value) {
 $index = 0;
 foreach($base as $key => $val) {
    if ($key==$beforeKey) break;
    $index++;
 }
 $end = array_splice($base, $index, count($base)-$index);
 $base[$newKey] = $value;
 return $base+$end;
}


$array = array('a'=>1,'z'=>2,'d'=>4);

$newArray=insert_key_before($array, 'z', 'c', 3);

var_export($array); // ( 'a' => 1, 'z' => 2, 'd' => 4, )

var_export($newArray); // array ( 'a' => 1, 'c' => 3, 'z' => 2, 'd' => 4, )
0 голосов
/ 27 января 2010

Вы можете определить свою собственную карту сортировки при выполнении пузырьковой сортировки по ключу. Это, вероятно, не очень эффективно, но это работает.

<code><pre>
<?php

$array = array('a'=>1,'z'=>2,'d'=>4);

$array['c'] = 3;

print_r( $array );

uksort( $array, 'sorter' );

print_r( $array );

function sorter( $a, $b )
{
    static $ordinality = array(
        'a' => 1
      , 'c' => 2
      , 'z' => 3
      , 'd' => 4
    );
    return $ordinality[$a] - $ordinality[$b];
}

?>

Вот подход, основанный на ArrayObject, использующий эту же концепцию

$array = new CitizenArray( array('a'=>1,'z'=>2,'d'=>4) );
$array['c'] = 3;

foreach ( $array as $key => $value )
{
    echo "$key: $value <br>";
}

class CitizenArray extends ArrayObject
{
    static protected $ordinality = array(
        'a' => 1
      , 'c' => 2
      , 'z' => 3
      , 'd' => 4
    );

    function offsetSet( $key, $value )
    {
        parent::offsetSet( $key, $value );
        $this->uksort( array( $this, 'sorter' ) );
    }

    function sorter( $a, $b )
    {
        return self::$ordinality[$a] - self::$ordinality[$b];
    }
}
0 голосов
/ 27 января 2010

Альтернативный подход заключается в дополнении структуры ассоциативного массива упорядоченным индексом, который определяет итеративный порядок ключей. Например:

$index = array('a','b','d');

// Add new value and update index
$array['c'] = 3;
array_splice($index, 2, 0, 'c');

// Iterate the array in order
foreach $index as $key {
   $value = $array[$key];
}
...