44

Is there a way to change all the numeric keys to "Name" without looping through the array (a native PHP function)?

[
    0 => 'blabla',
    1 => 'blabla',
    2 => 'blblll',
    // etc ...
]
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • 3
    Am I reading this right? It looks like you want all of the elements in an array to have the same key. – victoriah Nov 21 '08 at 13:14
  • I do, it's for purposes of translating the array to XML. –  Nov 21 '08 at 13:15
  • Array keys have to be unique, how are you trying to convert this to XML, can you post a code sample? – Neil Aitken Nov 21 '08 at 13:18
  • Using XML writer which does not allow numeric startElements. –  Nov 21 '08 at 13:19
  • copy the array values using array_values, put the new names in your order into a array, use array_combine to make the new array – sinaneker Jul 10 '13 at 12:49
  • See similar: http://stackoverflow.com/q/240660/287948 – Peter Krauss Jul 29 '13 at 18:57
  • 3
    For a canonical question having so many signposts, this is a decidedly poor question with vague/impossible requirements. Surely Stack Overflow has something better than this to offer the software development world. – mickmackusa Apr 17 '23 at 21:38

13 Answers13

106

If you have an array of keys that you want to use then use array_combine

Given $keys = array('a', 'b', 'c', ...) and your array, $list, then do this:

$list = array_combine($keys, array_values($list));

List will now be array('a' => 'blabla 1', ...) etc.

You have to use array_values to extract just the values from the array and not the old, numeric, keys.

That's nice and simple looking but array_values makes an entire copy of the array so you could have space issues. All we're doing here is letting php do the looping for us, not eliminate the loop. I'd be tempted to do something more like:

foreach ($list as $k => $v) {
   unset ($list[$k]);

   $new_key =  *some logic here*

   $list[$new_key] = $v;
}

I don't think it's all that more efficient than the first code but it provides more control and won't have issues with the length of the arrays.

Eric Goodwin
  • 2,996
  • 6
  • 25
  • 22
22

No, there is not, for starters, it is impossible to have an array with elements sharing the same key

$x =array(); 
$x['foo'] = 'bar' ; 
$x['foo'] = 'baz' ; #replaces 'bar'

Secondarily, if you wish to merely prefix the numbers so that

$x[0] --> $x['foo_0']  

That is computationally implausible to do without looping. No php functions presently exist for the task of "key-prefixing", and the closest thing is "extract" which will prefix numeric keys prior to making them variables.

The very simplest way is this:

function rekey( $input , $prefix ) { 
    $out = array(); 
    foreach( $input as $i => $v ) { 
        if ( is_numeric( $i ) ) { 
            $out[$prefix . $i] = $v; 
            continue; 
        }
        $out[$i] = $v;
    }
    return $out;
}

Additionally, upon reading XMLWriter usage, I believe you would be writing XML in a bad way.

<section> 
    <foo_0></foo_0>
   <foo_1></foo_1>
   <bar></bar>
   <foo_2></foo_2>
</section>

Is not good XML.

<section> 
   <foo></foo>
   <foo></foo>
   <bar></bar>
   <foo></foo>
</section>

Is better XML, because when intrepreted, the names being duplicate don't matter because they're all offset numerically like so:

section => { 
    0 => [ foo , {} ]
    1 => [ foo , {} ]
    2 => [ bar , {} ]
    3 => [ foo , {} ] 
}
Manoj Sharma
  • 1,467
  • 2
  • 13
  • 20
Kent Fredric
  • 56,416
  • 14
  • 107
  • 150
8

This is an example prefixing all the keys with an underscore.

We use array_combine to combine the array keys with the array values, but we first run an array_map function on the array keys, which takes a simple function that adds the prefix.

$prefix = '_';
$arr = array_combine(
    array_map(function($v) use ($prefix){
       return $prefix.$v;
    }, array_keys($arr)),
    array_values($arr)
);

See a live example here.

user16217248
  • 3,119
  • 19
  • 19
  • 37
Aurelien
  • 81
  • 1
  • 1
6

I added this for an answer to another question and seemed relevant. Hopefully might help someone that needs to change the value of the keys in an array. Uses built-in functions for php.

$inputArray = array('app_test' => 'test', 'app_two' => 'two');

/**
 * Used to remap keys of an array by removing the prefix passed in
 * 
 * Example:
 * $inputArray = array('app_test' => 'test', 'app_two' => 'two');
 * $keys = array_keys($inputArray);
 * array_walk($keys, 'removePrefix', 'app_');
 * $remappedArray = array_combine($keys, $inputArray);
 *
 * @param $value - key value to replace, should be from array_keys
 * @param $omit - unused, needed for prefix call
 * @param $prefix - prefix to string replace in keys
 */
function removePrefix(&$value, $omit, $prefix) {
    $value = str_replace($prefix, '', $value);
}

// first get all the keys to remap
$keys = array_keys($inputArray);

// perform internal iteration with prefix passed into walk function for dynamic replace of key
array_walk($keys, 'removePrefix', 'app_');

// combine the rewritten keys and overwrite the originals
$remappedArray = array_combine($keys, $inputArray);

// see full output of comparison
var_dump($inputArray);
var_dump($remappedArray);

Output:

array(2) {
  'attr_test' =>
  string(4) "test"
  'attr_two' =>
  string(3) "two"
}
array(2) {
  'test' =>
  string(4) "test"
  'two' =>
  string(3) "two"
}
akahunahi
  • 1,782
  • 23
  • 21
2

change array key name "group" to "children".

<?php
echo json_encode($data);

function array_change_key_name( $orig, $new, &$array ) {
    foreach ( $array as $k => $v ) {
        $res[ $k === $orig ? $new : $k ] = ( (is_array($v)||is_object($v)) ? array_change_key_name( $orig, $new, $v ) : $v );
    }
    return $res;
}

echo '<br>=====change "group" to "children"=====<br>';
$new = array_change_key_name("group" ,"children" , $data);
echo json_encode($new);
?>

result:

{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","group":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","group":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","group":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}

=====change "group" to "children"=====

{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","children":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","children":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","children":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}
Manoj Sharma
  • 1,467
  • 2
  • 13
  • 20
dingyuchi
  • 226
  • 2
  • 4
2

The solution to when you're using XMLWriter (native to PHP 5.2.x<) is using $xml->startElement('itemName'); this will replace the arrays key.

Mouna Cheikhna
  • 38,870
  • 10
  • 48
  • 69
1

I think that he want:

$a = array(1=>'first_name', 2=>'last_name');
$a = array_flip($a);

$a['first_name'] = 3;
$a = array_flip($a);

print_r($a);
LPL
  • 16,827
  • 6
  • 51
  • 95
intel
  • 27
  • 1
  • 1
    This makes all sorts of assumptions, such as the $a array values all being strings and all being unique. – Jason May 02 '13 at 14:44
  • It is easy to make assumptions when the question is vague, unclear, missing a [mcve], and ...impossible. – mickmackusa Apr 17 '23 at 23:28
1

To have the same key I think they must be in separate nested arrays.

for ($i = 0; $i < count($array); $i++) {
    $newArray[] = ['name' => $array[$i]];
};

Output:

0 => array:1 ["name" => "blabla"]
1 => array:1 ["name" => "blabla"]
2 => array:1 ["name" => "blblll"]
Jeffrey
  • 1,998
  • 1
  • 25
  • 22
0

I did this for an array of objects. Its basically creating new keys in the same array and unsetting the old keys.

public function transform($key, $results)
{
    foreach($results as $k=>$result)
    {
        if( property_exists($result, $key) )
        { 
            $results[$result->$key] = $result;
            unset($results[$k]);
        }
    }

    return $results;
}
Darren Cato
  • 1,382
  • 16
  • 22
0

Use array array_flip in php

$array = array ( [1] => Sell [2] => Buy [3] => Rent [4] => Jobs )
print_r(array_flip($array));
Array ( [Sell] => 1 [Buy] => 2 [Rent] => 3 [Jobs] => 4 ) 
Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453
0
<?php
    $array[$new_key] = $array[$old_key];
    unset($array[$old_key]);
?>
Red Web
  • 37
  • 2
0

You can not have the same array key twice. You would need to use arrays/objects.

$tupels = [
   [ 'item', 'blabla']
   [ 'item', 'blabla']   
   [ 'item', 'blblll']
];
$subArrays = [
   [ 'name' => 'item', value: 'blabla']
   [ 'name' => 'item', value: 'blabla']   
   [ 'name' => 'item', value: 'blblll']
];
$dataObjects = [
   new MyItemModel('blabla'),
   new MyItemModel('blabla'),
   new MyItemModel('blabla')
];

If your goal is an XML output - use a different viewpoint. translate/transform would mean that you create the XML from another data format - this requires you to define that format and include or add mapping information.

For most purposes it is a lot easier to generate a specific XML output using DOM or XMLWriter from your (known) data structures. At some point you iterate the array and create the item nodes.

With DOM it is possible to use array_map() or iteration.

$data = [
    0 => 'blabla',
    1 => 'blabla',
    2 => 'blblll',
    // etc ...
];

$document = new DOMDocument();
$document->append(
    $items = $document->createElement('items')
);
$items->append(
    ...array_map(
        function($text) use ($document) {
            $item = $document->createElement('item');
            $item->textContent = $text;
            return $item;
        },
        $data
    )
);

$document->formatOutput = true;
echo $document->saveXML();
<?xml version="1.0"?>
<items>
  <item>blabla</item>
  <item>blabla</item>
  <item>blblll</item>
</items>

append() is a DOM LV method that was implemented in PHP 8.0. It can take nodes and strings as arguments - strings will be added as text nodes.

Using arrap_map() allows to encapsulate the creation of child nodes into separate functions.

However a foreach() works just fine if you do not need the separation.

$document = new DOMDocument();
$document->append(
    $items = $document->createElement('items')
);
foreach ($data as $text) {
    $items->append(
        $item = $document->createElement('item')
    );
    $item->textContent = $text;
}

$document->formatOutput = true;
echo $document->saveXML();

The original method to append nodes is appendChild(). It allows you to append a single node. append() is just a shortcut for us lazy people.

$document = new DOMDocument();
$document->appendChild(
    $items = $document->createElement('items')
);
foreach ($data as $text) {
    $items->appendChild(
        $item = $document->createElement('item')
    );
    $item->textContent = $text;
}

$document->formatOutput = true;
echo $document->saveXML();

If you need to generate large XML document, XMLWriter is another option. It directly writes into a stream.

$writer = new XMLWriter();
$writer->openMemory();
$writer->setIndent(2);
$writer->startDocument();
$writer->startElement('items');
foreach ($data as $text) {
    $writer->writeElement('item', $text);
}
$writer->endElement();
$writer->endDocument();
echo $writer->outputMemory(); 
ThW
  • 19,120
  • 3
  • 22
  • 44
-4

You could create a new array containing that array, so:

<?php
$array = array();
$array['name'] = $oldArray;
?>
Sebastian Hoitz
  • 9,343
  • 13
  • 61
  • 77