Is this possible with preg_match? - php

i have strings that looks similar like this:
"size:34,35,36,36,37|color:blue,red,white"
is it possible to match all the colors in a preg_match(_all)?
so that i will get "blue", "red" and "white" in the output array?
the colors can be whatever, so i cant go (blue|red|white)

Explode on |
Explode on :
Explode on ,
???
Profit!
Code
IMHO using regular expressions like what's been suggested in the other answers is a much "uglier" solution than something simple like so:
$input = 'size:34,35,36,36,37|color:blue,red,white|undercoating:yes,no,maybe,42';
function get_option($name, $string) {
$raw_opts = explode('|', $string);
$pattern = sprintf('/^%s:/', $name);
foreach( $raw_opts as $opt_str ) {
if( preg_match($pattern, $opt_str) ) {
$temp = explode(':', $opt_str);
return $opts = explode(',', $temp[1]);
}
}
return false; //no match
}
function get_all_options($string) {
$options = array();
$raw_opts = explode('|', $string);
foreach( $raw_opts as $opt_str ) {
$temp = explode(':', $opt_str);
$options[$temp[0]] = explode(',', $temp[1]);
}
return $options;
}
print_r(get_option('undercoating', $input));
print_r(get_all_options($input));
Output:
Array
(
[0] => yes
[1] => no
[2] => maybe
[3] => 42
)
Array
(
[size] => Array
(
[0] => 34
[1] => 35
[2] => 36
[3] => 36
[4] => 37
)
[color] => Array
(
[0] => blue
[1] => red
[2] => white
)
[undercoating] => Array
(
[0] => yes
[1] => no
[2] => maybe
[3] => 42
)
)

You can achieve it in a round about way with preg_match_all() but I'd recommend explode instead.
preg_match_all('/([a-z]+)(?:,|$)/', "size:34,35,36,36,37|color:blue,red,white", $a);
print_r($a[1]);

I think it's possible with lookbehind:
/(?<=(^|\|)color:([^,|],)*)[^,|](?=\||,|$)/g
(for preg_match_all)
Your explode solution is obviously cleaner :-)

Related

Is there any oneliner for a kind of explode and concat in PHP

I got string like 1_2_3_4_5 and I want an array like this:
array(
[0] = 1
[1] = 1_2
[2] = 1_2_3
[3] = 1_2_3_4
[4] = 1_2_3_4_5
)
Any idea for a oneliner?
just for fun using substr
$st = '1_2_3_4_5';
$num[]=$st;
while($pos=strrpos($st,'_')){
$num[]=$st=substr($st,0,$pos);
}sort($num);
print_r($num);
Output
(
[0] => 1
[1] => 1_2
[2] => 1_2_3
[3] => 1_2_3_4
[4] => 1_2_3_4_5
)
<?php
$input = '1_2_3_4_5';
// Get an array with 1, 2, 3, 4 and 5
$parts = explode('_', $input);
$output = [];
$i = 1;
foreach ($parts as $part) {
// array_slice() will take 1 to n elements from the array of numbers
$values = array_slice($parts, 0, $i++);
// Join the values
$output[] = implode('_', $values);
}
print_r($output);
It will show this:
Array
(
[0] => 1
[1] => 1_2
[2] => 1_2_3
[3] => 1_2_3_4
[4] => 1_2_3_4_5
)
Try it at 3V4L.

PHP Explode string between two characters to arrays? (Noob question)

Hello :) I am a beginner in PHP.
I tried several times but did not succeed
I would like to parse a String like :
[1,[01,11,12],[20,21,22]]
to
`
arr[0][0]=>1
arr[1][0]=>01
arr[1][1]=>11
arr[1][2]=>12
arr[2][0]=>20
arr[2][1]=>21
arr[2][2]=>22
`
You can split your string on a comma that is not enclosed by [ and ] using this regex (inspired by this answer) with preg_split:
,(?![^\[]*\])
and then trim surrounding [ and ] from the resultant parts and split those strings on commas into succeeding elements of the output array. For example:
$string = '[1,[01,11,12] ,4 ,5, [20,21,22]]';
$parts = preg_split('/,(?![^\[]*\])/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
$output = array();
foreach ($parts as $part) {
$part = trim($part, '[] ');
$output[] = explode(',', $part);
}
print_r($output);
Output:
Array
(
[0] => Array
(
[0] => 1
)
[1] => Array
(
[0] => 01
[1] => 11
[2] => 12
)
[2] => Array
(
[0] => 4
)
[3] => Array
(
[0] => 5
)
[4] => Array
(
[0] => 20
[1] => 21
[2] => 22
)
)
Demo on 3v4l.org
If you're 100% certain of the source and safety of the string, you can also just use eval:
eval("\$output = $string;");
The result will be the same.

PHP return value within array

I am trying to retrieve all the first objects from an array, this is how my array looks like:
Array
(
[0] => lorem;1;banana
[1] => ipsum;2;apple
[2] => dolor;3;grapefruit
[3] => sit;4;pineapple;
[4] => amet;5;orange
)
I want it to return a certain value of that and store it in a variable, so that I can get all the fruit names, for example. Any way to do this?
You can use array_map:
$fruits = array_map(function($item) {
$arr = explode(';', $item);
return $arr[2];
}, $array);
var_dump($fruits);
Assuming the fruits always come last and may or may not have a trailing semicolon, you can use
preg_replace — Perform a regular expression search and replace
Example:
$data = [
'lorem;1;banana',
'ipsum;2;apple',
'dolor;3;grapefruit',
'sit;4;pineapple;',
'amet;5;orange'
];
$fruits = preg_replace('#.+;(.+?)[;]*$#', "$1", $data);
print_r($fruits);
The pattern means match everything up and including to a semicolon (greedy), then capture the content up to the end ending with or without a semicolon.
Output:
Array
(
[0] => banana
[1] => apple
[2] => grapefruit
[3] => pineapple
[4] => orange
)
You can use array_walk_recursive function and change your array item as per requirement.
use following code which will give you appropriate output:
$test = array(0 => 'lorem;1;banana', 1 => 'ipsum;2;apple', 2 => 'dolor;3;grapefruit',3 => 'sit;4;pineapple;',4 => 'amet;5;orange');
array_walk_recursive($test, 'test');
function test(&$item, $key)
{
$itemArray = explode(';', $item);
$item = $itemArray[2];
}
For the sake of completeness, those strings can be easily parsed as csv with str_getcsv
$a = array(
'lorem;1;banana',
'ipsum;2;apple',
'dolor;3;grapefruit',
'sit;4;pineapple;',
'amet;5;orange'
);
foreach($a as $line){
$csvString = str_getcsv($line,';');
$fruits[] = $csvString[2];
}
print_r($fruits);
Will output
Array
(
[0] => banana
[1] => apple
[2] => grapefruit
[3] => pineapple
[4] => orange
)

convert a string to multi dimensional array in php

I'm having trouble converting a string to a multi-dimensional array in php. This is my string:
$String = a,b,c|d,e,f|g,h,y|
This is what I'm trying:
$one=explode("|",$String);
foreach ($one as $item)
{
$one=explode(",",$one);
}
I'd like to create this array:
$array={ {a,b,c}, {d,e,f}, {g,h,y} };
Try with -
$one=explode("|",$String);
$array = array();
foreach ($one as $item){
$array[] = explode(",",$item);
}
Try this code:
$string = 'a,b,c|d,e,f|g,h,y|';
$arr = array_map(function($iter){ return explode(',',$iter);},explode('|',$string));
Hope it help a bit.
You have almost done it right, except for the cycle part. Try this
$result = [];
$String = 'a,b,c|d,e,f|g,h,y|';
$firstDimension = explode('|', $String); // Divide by | symbol
foreach($firstDimension as $temp) {
// Take each result of division and explode it by , symbol and save to result
$result[] = explode(',', $temp);
}
print_r($result);
Try this-
$String = 'a,b,c|d,e,f|g,h,y|';
$one = array_filter(explode("|", $String));
print_r($one); //Array ( [0] => a,b,c [1] => d,e,f [2] => g,h,y )
$result = array_map('v', $one);
function v($one) {
return explode(',',$one);
}
print_r($result); // Array ( [0] => Array ( [0] => a [1] => b [2] => c ) [1] => Array ( [0] => d [1] => e [2] => f ) [2] => Array ( [0] => g [1] => h [2] => y ) )
Use this code
$String= 'a,b,c|d,e,f|g,h,y|';
$one=explode("|",$String);
print_r(array_filter($one));
Output will be
Array
(
[0] => a,b,c
[1] => d,e,f
[2] => g,h,y
)

PHP Group array by values

I have an array like this:
Array (
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
[4] => ing_2_ing
[5] => ing_2_amount
[6] => ing_2_det
[7] => ing_2_meas
)
And I want to group the values into an array like this:
Array (
[0] => Array(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[1] => Array(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)
There may be many other items named like that: ing_NUMBER_type
How do I group the first array to the way I want it? I tried this, but for some reason, strpos() sometimes fails:
$i = 1;
foreach ($firstArray as $t) {
if (strpos($t, (string)$i)) {
$secondArray[--$i][] = $t;
} else {
$i++;
}
}
What is wrong? Can you advice?
It depends what you are trying to achieve, if you want to split array by chunks use array_chunk method and if you are trying to create multidimensional array based on number you can use sscanf method in your loop to parse values:
$result = array();
foreach ($firstArray as $value)
{
$n = sscanf($value, 'ing_%d_%s', $id, $string);
if ($n > 1)
{
$result[$id][] = $value;
}
}
<?php
$ary1 = array("ing_1_ing","ing_1_amount","ing_1_det","ing_1_meas","ing_2_ing","ing_2_amount","ing_2_det","ing_2_meas");
foreach($ary1 as $val)
{
$parts = explode("_",$val);
$ary2[$parts[1]][]=$val;
}
?>
This creates:
Array
(
[1] => Array
(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[2] => Array
(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)
What I'd do is something like this:
$result = array();
foreach ($firstArray as $value)
{
preg_match('/^ing_(\d+)_/', $value, $matches);
$number = $matches[1];
if (!array_key_exists($number, $result))
$result[$number] = array();
$result[$number][] = $value;
}
Basically you iterate through your first array, see what number is there, and put it in the right location in your final array.
EDIT. If you know you'll always have the numbers start from 1, you can replace $number = $matches[1]; for $number = $matches[1] - 1;, this way you'll get exactly the same result you posted as your example.

Categories