Exploding and replacing one array field
So, I have an array that, for unrelated reasons, has one imploded field in itself. Now, I'm interested in exploding the string in that field, and replacing that field with the results of the blast. I kinda-sorta have a working solution here, but it looks clunky, and I'm interested in something more efficient. Or at least aesthetically pleasing.
Example array:
$items = array(
'name' => 'shirt',
'kind' => 'blue|long|L',
'price' => 10,
'amount' => 5);
And the goal is to replace the 'kind'
field with 'color', 'lenght', 'size'
fields.
So fa开发者_JS百科r I've got:
$attribs = array('color', 'lenght', 'size'); // future indices
$temp = explode("|", $items['kind']); // exploding the field
foreach ($items as $key => $value) { // iterating through old array
if ($key == 'kind') {
foreach ($temp as $k => $v) { // iterating through exploded array
$new_items[$attribs[$k]] = $v; // assigning new array, exploded values
}
}
else $new_items[$key] = $value; // assigning new array, untouched values
}
This should (I'm writing by heart, don't have the access to my own code, and I can't verify the one I just wrote... so if there's any errors, I apologize) result in a new array, that looks something like this:
$new_items = array(
'name' => 'shirt',
'color' => 'blue',
'lenght' => 'long',
'size' => 'L',
'price' => 10,
'amount' => 5);
I could, for instance, just append those values to the $items
array and unset($items['kind'])
, but that would throw the order out of whack, and I kinda need it for subsequent foreach
loops.
So, is there an easier way to do it?
EDIT: (Reply to Visage and Ignacio - since reply messes the code up) If I call one in a foreach loop, it calls them in a specific order. If I just append, I mess with the order I need for a table display. I'd have to complicate the display code, which relies on a set way I get the initial data. Currently, I display data with (or equivalent):
foreach($new_items as $v) echo "<td>$v</td>\n";
If I just append, I'd have to do something like:
echo "<td>$new_items['name']</td>\n";
foreach ($attribs as $v) echo "<td>$new_items[$v]</td>\n";
echo "<td>$new_items['price']</td>\n";
echo "<td>$new_items['amount']</td>\n";
Associative arrays generally should not depend on order. I would consider modifying the later code to just index the array directly and forgo the loop.
Try this:
$items = array( 'name' => 'shirt', 'kind' => 'blue|long|L', 'price' => 10, 'amount' => 5);
list($items['color'], $items['lenght'], $items['size'])=explode("|",$items['kind']);
unset $items['kind'];
I've not tested it but it should work.
Associative arrays do not have an order, so you can just unset the keys you no longer want and then simply assign the new values to new keys.
one way
$items = array(
'name' => 'shirt',
'kind' => 'blue|long|L',
'price' => 10,
'amount' => 5);
$attribs = array('color', 'lenght', 'size');
$temp = explode("|", $items['kind']);
$s = array_combine($attribs,$temp);
unset($items["kind"]);
print_r( array_merge( $items, $s) );
This should retain the ordering because it splits the keys and values into two numerically ordered arrays and combines them at the end. It isn't more efficient, but the code is easier to read.
$kind_keys = array('color', 'length', 'size');
$kind_values = explode("|", $items['kind']);
$keys = array_keys($items);
$values = array_values($items);
$index = array_search('kind', $keys);
// Put the new keys/values in:
array_splice($keys, $index, 1, $kind_keys);
array_splice($values, $index, 1, $kind_values);
// combine the result into a new array:
$result = array_combine($keys, $values));
精彩评论