views:

67

answers:

4

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 far 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";
A: 

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.

mck89
Well, it does work, but appends to the end (so, same problem as explained in the edit). Curiously, though... when I do a print_r($items) with your code, it doesn't list keys as name-price-cost-color-lenght-size (as I expect it, and as it does for ghostdog's code), but in the order name-price-cost-size-lenght-color. The three got from explode are reversed. How come?
Xipe_Totec
+1  A: 

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.

Ignacio Vazquez-Abrams
A: 

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.

Visage
A: 

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