user9819807
user9819807

Reputation:

pattern for changing key value in array

I have an array:

[ 0 ] => 3000mAh battery
[ 1 ] => charges 1 smartphone
[ 2 ] => input: 5W (5V, 1A) micro USB port
[ 3 ] => output: Micro USB cable: 7.5W (5V, 1.5A)
[ 4 ] => recharge time 3-4 hours
[ 5 ] => includes Micro USB cable
[ 6 ] => 1-Year Limited Warranty

I want to remove these keys and put the part of the string that is already in value. The final result that i want is:

[ battery ] => 3000mAh 
[ charges ] =>  1 smartphone
[ input ] =>  5W (5V, 1A) micro USB port
[ output ] =>  Micro USB cable: 7.5W (5V, 1.5A)
[ recharge ] =>  time 3-4 hours
[ includes ] =>  Micro USB cable
[ Warranty ] => 1-Year Limited 

There is three condition here:

1) if string have : then take text before first : and put it in key example:

[ 2 ] => input: 5W (5V, 1A) micro USB port
[ input ] =>  5W (5V, 1A) micro USB port

2) if string begins with number take last word of string and put it like key:

[ 0 ] => 3000mAh battery
[ battery ] => 3000mAh 

3) if string begins with letter take first word of string and put it like key:

[ 1 ] => charges 1 smartphone
[ charges ] =>  1 smartphone

This is my code that solved first condition, can you help me how i can do the rest?

$new_array= array_reduce($old_array, function ($c, $v){ 
            preg_match('/^([^:]+):\s+(.*)$/', $v, $m); 
            if(!empty($m[1])){
                return array_merge($c, array($m[1] => $m[2]));}
            else{
                return array();
            }
        },[]);

Upvotes: 1

Views: 52

Answers (2)

Nigel Ren
Nigel Ren

Reputation: 57131

Rather than use regexes - just using explode() can break down the items quicker and also (IMHO) clearer. This first looks to split it with :, if this produces a result, then use the first item as the key and the rest as the content. If this fails then use a space and just check which version to use (using is_numeric() on the first character)...

$output = [];
foreach ( $data as $item )  {
    $split = explode(":", $item );
    if ( count($split) > 1 )   {
        $key = array_shift($split);
        $join = ":";
    }
    else    {
        $split = explode(" ", $item);
        if ( strtolower($split[count($split)-1]) == "warranty" ||
                is_numeric($item[0]) ){
            $key = array_pop($split);
        }
        else    {
            $key = array_shift($split);
        }

        $join = " ";
    }
    $output[$key] = implode($join, $split);
}

print_r($output);

Upvotes: 1

The fourth bird
The fourth bird

Reputation: 163477

You could check the first characters by using ctype_alpha or is_numeric. To check for a : you could use explode and check if the count is greater than 1.

To write the value, you could use implode with a space as the glue.

$result = [];

foreach ($items as $item) {
    $res = explode(':', $item);
    if (count($res) > 1) {
        $key = $res[0];
        array_shift($res);
        $result[$key] = implode(':', $res);
        continue;
    }
    if (is_numeric($item[0])) {
        $parts = (explode(' ', $item));
        $key = array_pop($parts);
        $result[$key] = implode(' ', $parts);
        continue;
    }
    if (ctype_alpha ($item[0])) {
        $parts = explode(' ', $item);
        $key = array_shift($parts);
        $result[$key] = implode(' ', $parts);
    }
}

print_r($result);

Demo

Upvotes: 1

Related Questions