0

I have a string in the following form:

$my_original_string = "A value1,A value2,E value3,A value4";

The first letter is a sort of label, the value is associated with a label.

I must manipulate and convert my string to the following:

$my_converted_string = "A: value1 value2 value4, E: value3";

With a simple loop, I created an array $temp:

$my_original_string = "A value1,A value2,E value3,A value4";

$original_string_to_array = explode(",", $my_original_string);
$o_len = count($original_string_to_array);

$temp = [];

for($i=0; $i<$o_len; $i++){
    $temp[explode(" ",$original_string_to_array[$i])[0]][] = explode(" ",$original_string_to_array[$i])[1];
}

print_r($temp);

/*
Result:

Array
(
    [A] => Array
        (
            [0] => value1
            [1] => value2
            [2] => value4
        )

    [E] => Array
        (
            [0] => value3
        )

)
*/

Starting from here, I could eventually loop again to build my new string. Or maybe I could do it even in one loop.

But, is there anything better I could do? I checked the capabilities of array_map, array_filter and array_walk but I could not find a way to apply them in this particular case.

Thanks in advance.

3
  • use implode() to turn an array into a comma-separated string. Commented Nov 19, 2020 at 7:55
  • You can't use array_map() because it only gets the values, not the keys. So use a foreach() loop to push each key and the imploded values into another array, then implode that to get the final result. Commented Nov 19, 2020 at 7:57
  • @Barmar: no problem for implode. What I was searching for was a solution without a loop and I felt this was not possible (you confirmed this too) Commented Nov 19, 2020 at 8:43

2 Answers 2

2

A couple of coding improvements would reduce some of the code, using a foreach instead of the for (where you also have to count the items). Also inside the loop, use explode() once to reduce repetition of the code.

This also inside the loop checks if the key is already present. If it is, it just appends the new value, if it isn't it creates a new value with the key and value. When it outputs the value, it uses implode() to stick the values back together...

$my_original_string = "A value1,A value2,E value3,A value4";

$originalArray = explode(",", $my_original_string);
$output = [];
foreach($originalArray as $item )   {
    [$key, $value] = explode(" ", $item, 2);
    $output[$key] = (isset($output[$key])) ? $output[$key]." ".$value 
                        : "$key: $value";
}
print_r(implode(", ", $output));

gives...

A: value1 value2 value4, E: value3
Sign up to request clarification or add additional context in comments.

5 Comments

Ok, that's fine, but it confirms there's no solution without a loop :-)
Even the array_ functions are effectively a loop - and are sometime less efficient. There may be another way to do it, but I tend to go for readability than something that may look neat (most of the time).
What's the point of making $output an associative array? implode() doesn't use the keys.
@Barmar, so you can add the value to the correct list (a list of the values for A or E).
@NigelRen Of course, I don't actually hate loops, even if sometimes I tend to prefer readibility over performance, expecially when the code efficiency isn't that important :-)
1

Although you can use array_map

$string = "A value1,A value2,E value3,A value4,B value5";

$split = explode(',', $string);
$walk = array();
$map = array_map(function($a) use(&$walk) {
  list($key,$value) = explode(' ',$a);
  $walk[$key] = (isset($walk[$key]) ?
                sprintf('%s %s',$walk[$key],$value)
                : sprintf('%s: %s',$key,$value));
  return $walk;
}, $split);

$str = implode(',',array_pop($map));
echo $str;

return output with :

A: value1 value2 value4,B: value5,E: value3

or in array

Array
(
    [A] => A: value1 value2 value4
    [B] => B: value5
    [E] => E: value3
)

Note: if you use $map you need to use array_pop to get last element, also you can use $walk if you don't like to use array_pop

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.