sscanf() has its merits for this task. It will accommodate strings that only contain the item text and no price. It will cast the price directly as a float type value. Unfortunately, it is not equipped to trim the trailing space from the item text (before the opening parenthesis). Also, to prevent a subsequent value without a price from being assigned the price from the previous item, the price variable will need to be unset.
Code: (Demo)
$result = [];
foreach ($array as $v) {
sscanf($v, '%[^(](+£%f)', $item, $price);
$result[rtrim($item)] = $price ?? 0;
unset($price);
}
var_export($result);
Or unconditionally append (+£0) to each input string to ensure a price. (Demo)
$result = [];
foreach ($array as $v) {
sscanf($v . ' (+£0)', '%[^(](+£%f)', $item, $price);
$result[rtrim($item)] = $price;
}
var_export($result);
preg_split() can be used as well without a terribly cumbersome regex pattern. (Demo)
$result = [];
foreach ($array as $v) {
$a = preg_split('/ \(\+£([^)]+)\)/', $v, 2, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$result[$a[0]] = (float) ($a[1] ?? 0);
}
var_export($result);
Here's a deviation from @nobody's preg_match() snippet: (Demo)
$result = [];
foreach ($array as $v) {
$result += preg_match("/(.+) \(\+£([^)]+)\)/", $v, $m) ? [$m[1] => (float) $m[2]] : [$v => 0];
}
var_export($result);