Ice
Ice

Reputation:

Is there a way to change all keys in a flat indexed array to the same string ("Name")?

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 ...
]

Upvotes: 44

Views: 123046

Answers (13)

ThW
ThW

Reputation: 19492

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(); 

Upvotes: 0

Aurelien
Aurelien

Reputation: 81

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.

Upvotes: 8

dingyuchi
dingyuchi

Reputation: 226

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"}]}]}]}]}

Upvotes: 2

Kent Fredric
Kent Fredric

Reputation: 57354

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 , {} ] 
}

Upvotes: 22

Jeffrey
Jeffrey

Reputation: 2106

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"]

Upvotes: 1

akahunahi
akahunahi

Reputation: 1822

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"
}

Upvotes: 6

Red Web
Red Web

Reputation: 37

<?php
    $array[$new_key] = $array[$old_key];
    unset($array[$old_key]);
?>

Upvotes: 0

Darren Cato
Darren Cato

Reputation: 1372

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;
}

Upvotes: 0

Ice
Ice

Reputation:

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.

Upvotes: 2

intel
intel

Reputation: 27

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

Upvotes: 1

user198766
user198766

Reputation:

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 ) 

Upvotes: 0

Eric Goodwin
Eric Goodwin

Reputation: 2986

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.

Upvotes: 105

Sebastian Hoitz
Sebastian Hoitz

Reputation: 9383

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

<?php
$array = array();
$array['name'] = $oldArray;
?>

Upvotes: -4

Related Questions