If I have a string like:
123*23*6594*2*-10*12
How can I extract the single numbers, in the string separated by *? That is, I want this output:
a=123, b=23, c=6594, d=2, e=-10, f=12.
Flexible:
$vars = range('a', 'z');
$vals = explode('*', $string);
$result = array_combine(array_slice($vars, 0, count($vals)), $vals);
Result:
Array
(
[a] => 123
[b] => 23
[c] => 6594
[d] => 2
[e] => -10
[f] => 12
)
Just for the sheer fun of setting the result as an iterable (rather than an actual array) with the alpha keys in a slightly different manner:
$data = '123*23*6594*2*-10*12';
function dataseries($data) {
$key = 'a';
while (($x = strpos($data, '*')) !== false) {
yield $key++ => substr($data, 0, $x);
$data = substr($data, ++$x);
}
yield $key++ => $data;
}
foreach(dataseries($data) as $key => $value) {
echo $key, ' = ', $value, PHP_EOL;
}
Requires PHP >= 5.5.0
You can use simple as this :
$str = "123*23*6594*2*-10*12";
$arr = explode("*",$str);
$arr['a']=$arr[0];
$arr['b']=$arr[1];
$arr['c']=$arr[2];
$arr['d']=$arr[3];
$arr['e']=$arr[4];
$arr['f']=$arr[5];
echo "a=" .$arr['a'] ." b=". $arr['b']." c=". $arr['c']." d=". $arr['d']." e=". $arr['e']." f=". $arr['f'];
EDIT:
To accomplish Rizier123 wish :
$str = "123*23*6594*2*-10*12";
$arr = explode("*",$str);
$vars = range('a', 'z');
foreach ($arr as $val => $key){
echo $vars[$val]."=".$key."<br>";
}
something like:
list($a,$b,$c,$d,$e,$f) = explode("*", $str);
Just a guess ;)
Related
This question already has answers here:
PHP - split String in Key/Value pairs
(5 answers)
Convert backslash-delimited string into an associative array
(4 answers)
Closed 12 months ago.
i have a string like
$str = "1-a,2-b,3-c";
i want to convert it into a single array like this
$array = [
1 => "a",
2 => "b",
3 => "c"
];
what i do is
$str = "1-a,2-b,3-c";
$array = [];
$strex = explode(",", $str);
foreach ($strex as $str2) {
$alphanumeric = explode("-", $str2);
$array[$alphanumeric[0]] = $alphanumeric[1];
}
can i do this in a better way?
You can use preg_match_all for this:
<?php
$str = "1-a,2-b,3-c";
preg_match_all('/[0-9]/', $str, $keys);
preg_match_all('/[a-zA-Z]/', $str, $values);
$new = array_combine($keys[0], $values[0]);
echo '<pre>'. print_r($new, 1) .'</pre>';
here we take your string, explode() it and then preg_match_all the $value using patterns:
/[0-9]/ -> numeric value
/[a-zA-Z]/ -> letter
then use array_combine to get it into one array
Thanks to u_mulder, can shorten this further:
<?php
$str = "1-a,2-b,3-c";
preg_match_all('/(\d+)\-([a-z]+)/', $str, $matches);
$new = array_combine($matches[1], $matches[2]);
echo '<pre>'. print_r($new, 1) .'</pre>';
just a little benchmark:
5000 iterations
Debian stretch, php 7.3
parsed string: "1-a,2-b,3-c,4-d,5-e,6-f,7-g,8-h,9-i"
[edit] Updated with the last 2 proposals [/edit]
You can use preg_split with array_filter and array_combine,
function odd($var)
{
// returns whether the input integer is odd
return $var & 1;
}
function even($var)
{
// returns whether the input integer is even
return !($var & 1);
}
$str = "1-a,2-b,3-c";
$temp = preg_split("/(-|,)/", $str); // spliting with - and , as said multiple delim
$result =array_combine(array_filter($temp, "even", ARRAY_FILTER_USE_KEY),
array_filter($temp, "odd",ARRAY_FILTER_USE_KEY));
print_r($result);
array_filter — Filters elements of an array using a callback function
Note:- ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value
array_combine — Creates an array by using one array for keys and another for its values
Demo
Output:-
Array
(
[1] => a
[2] => b
[3] => c
)
One way to do with array_map(),
<?php
$my_string = '1-a,2-b,3-c';
$my_array = array_map(function($val) {list($key,$value) = explode('-', $val); return [$key=>$value];}, explode(',', $my_string));
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($my_array)) as $k=>$v){
$result[$k]=$v;
}
print_r($result);
?>
WORKING DEMO: https://3v4l.org/aYmOH
Tokens all the way down...
<?php
$str = '1-a,2-b,3-c';
$token = '-,';
if($n = strtok($str, $token))
$array[$n] = strtok($token);
while($n = strtok($token))
$array[$n] = strtok($token);
var_export($array);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
Or perhaps more terse without the first if...:
$array = [];
while($n = $array ? strtok($token) : strtok($str, $token))
$array[$n] = strtok($token);
Not a better way but one more example:
$str = "1-a,2-b,3-c";
$arr1 = explode(",", preg_replace("/\-([a-zA-Z]+)/", "", $str));
$arr2 = explode(",", preg_replace("/([0-9]+)\-/", "", $str));
print_r(array_combine($arr1, $arr2));
Mandatory one-liner (your mileage may vary):
<?php
parse_str(str_replace([',', '-'], ['&', '='], '1-a,2-b,3-c'), $output);
var_export($output);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
You can do one split on both the , and -, and then iterate through picking off every other pair ($k&1 is a check for an odd index):
<?php
$str = '1-a,2-b,3-c';
foreach(preg_split('/[,-]/', $str) as $k=>$v) {
$k&1 && $output[$last] = $v;
$last = $v;
}
var_export($output);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
The preg_split array looks like this:
array (
0 => '1',
1 => 'a',
2 => '2',
3 => 'b',
4 => '3',
5 => 'c',
)
This one explodes the string as the OP has on the comma, forming the pairs: (1-a) and (2-b) etc. and then explodes those pairs. Finally array_column is used to create the associated array:
<?php
$str = '1-a,2-b,3-c';
$output =
array_column(
array_map(
function($str) { return explode('-', $str); },
explode(',', $str)
),
1,
0
);
var_export($output);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
Do you have an idea, how can a string be converted to a variable, e.g.
there is a string -> $string = 'one|two|three';
there is an array -> $arr = array('one' => array('two' => array('three' => 'WELCOME')));
I want to use all with explode(); exploded values to access the array $arr. I tried this code:
$c = explode('|', $string);
$str = 'arr[' . implode('][', $c) . ']';
echo $$str;
It doesnt work, sadly :( Any ideas?
You're doing it wrong.
You can do what you want with a loop to go through the array level by level
$string = 'one|two|three';
$arr = array('one' => array('two' => array('three' => 'WELCOME')));
$c = explode('|', $string);
$result = $arr;
foreach($c as $key)
$result = $result[$key];
echo $result; // WELCOME
Here's a sort of recursive function:
$ex_keys = array('one', 'two', 'three');
$ex_arr = array('one' => array('two' => array('three' => 'WELCOME')));
function get_recursive_var($keys, $arr) {
if (sizeof($keys) == 1)
return $arr[$keys[0]];
else {
$key = array_shift($keys);
return get_recursive_var($keys, $arr[$key]);
}
}
var_dump(get_recursive_var($ex_keys, $ex_arr));
is there a way to use explode function to explode only by last delimiter occurrence?
$string = "one_two_ ... _three_four";
$explodeResultArray = explode("_", $string);
Result Should Be:
echo $explodeResultArray[0]; // "one_two_three ...";
echo $explodeResultArray[1]; // "four";
Straightforward:
$parts = explode('_', $string);
$last = array_pop($parts);
$parts = array(implode('_', $parts), $last);
echo $parts[0]; // outputs "one_two_three"
Regular expressions:
$parts = preg_split('~_(?=[^_]*$)~', $string);
echo $parts[0]; // outputs "one_two_three"
String reverse:
$reversedParts = explode('_', strrev($string), 2);
echo strrev($reversedParts[0]); // outputs "four"
There is no need for a workaround. explode() accepts a negative limit.
$string = "one_two_three_four";
$part = implode('_', explode('_', $string, -1));
echo $part;
Result is
one_two_three
I chose to use substring becasue you want a string up to a particular point:
$string = "one_two_three_four_five_six_seven";
$part1 = substr("$string",0, strrpos($string,'_'));
$part2 = substr("$string", (strrpos($string,'_') + 1));
var_dump($part1,$part2);
RESULTS:
string(27) "one_two_three_four_five_six"
string(5) "seven"
You could do the following:
$string = "one_two_three_four";
$explode = explode('_', $string); // split all parts
$end = '';
$begin = '';
if(count($explode) > 0){
$end = array_pop($explode); // removes the last element, and returns it
if(count($explode) > 0){
$begin = implode('_', $explode); // glue the remaining pieces back together
}
}
EDIT:
array_shift should have been array_pop
<?php
$lastPos = strrpos($string, '_');
if ($lastPos !== false) {
$start = substr($string, 0, $lastPos);
$end = substr($string, $lastPos+1);
} else {
// no delimeter found!
}
If you only care about the last part, it's even simpler.
<?php
$end = substr(strrchr($string, '_'), 1);
Use preg_match()
$string = "one_two_three_four";
$arr = array();
preg_match("/(^.*)_(.*?)$/", $string, $arr);
print_r($arr);
Output: Array ( [0] => one_two_three_four [1] => one_two_three [2] => four )
use end + explode
$explodeResultArray = end(explode("_", $string));
$explodeResultArray will = four
// reverse $string right after definition
$string = "one_two_three_four_five_six";
$string = implode("_",array_reverse(explode("_",$string)));
// chop off the first part
list($result, $string) = explode("_", $string, 2);
echo "$result --- $string";
Output:
six --- five_four_three_two_one
$explodeResultArray = explode("_", $string);
$last_item = end($explodeResultArray);
$key = count($explodeResultArray) - 1;
unset($explodeResultArray[$key]);
$arr[] = (implode($explodeResultArray,'_'));
$arr[] = $last_item;
print_r($arr);
Output
Array
(
[0] => one_two_ ... _three
[1] => four
)
I had similar needs and inspired by #NLZ's answer I've made a reusable function with the same features as regular explode(), but backwards (although I added an option to reverse the array order contra regular explode()):
function backward_explode($delimiter, $string, $limit = null, $keep_order = true) {
if ((string)$delimiter === "") {
return false;
}
if ($limit === 0 || $limit === 1) {
return array($string);
}
$explode = explode($delimiter, $string);
if ($limit === null || $limit === count($explode)) {
return $keep_order? $explode : array_reverse($explode);
}
$parts = array();
if ($limit > 0) {
for ($i = 1; $i < $limit; $i++) {
$parts[] = array_pop($explode);
}
$remainder = implode($delimiter, $explode);
$parts[] = $remainder;
if ($keep_order) {
$parts = array_reverse($parts);
}
} else {
if (strpos($string, $delimiter) === false) {
return array();
}
$parts = $explode;
array_splice($parts, 0, abs($limit));
if (!$keep_order) {
$parts = array_reverse($parts);
}
}
return $parts;
}
(Also as a gist.)
So with:
$string = 'one two three four';
var_dump(backward_explode(' ', $string));
var_dump(backward_explode(' ', $string, 2));
var_dump(backward_explode(' ', $string, 3));
var_dump(backward_explode(' ', $string, 2, false));
var_dump(backward_explode(' ', $string, -1));
var_dump(backward_explode(' ', $string, 1)); // same as with $limit = 0
var_dump(backward_explode('#', $string, -2));
var_dump(backward_explode('', $string, 3));
We get:
array (size=4)
0 => string 'one' (length=3)
1 => string 'two' (length=3)
2 => string 'three' (length=5)
3 => string 'four' (length=4)
array (size=2)
0 => string 'one two three' (length=13)
1 => string 'four' (length=4)
array (size=3)
0 => string 'one two' (length=7)
1 => string 'three' (length=5)
2 => string 'four' (length=4)
array (size=2)
0 => string 'four' (length=4)
1 => string 'one two three' (length=13)
array (size=3)
0 => string 'two' (length=3)
1 => string 'three' (length=5)
2 => string 'four' (length=4)
array (size=1)
0 => string 'one two three four' (length=18)
array (size=0)
empty
boolean false
For such a taks, you can just use strstr and strrchr:
$valueBeforeLastUnderscore = rtrim(strrev(strstr(strrev($value), '_')), '_');
$valueAfterLastUnderscore = ltrim(strrchr($value, '_'), '_');
That being said, I like the regular expression answer more.
simply use sub string
substr($string ,stripos($string ,'_'))
I have one string like:-
$attributes = "id=1 username=puneet mobile=0987778987 u_id=232";
Now, I want to get it in following associative array format:-
$attributes{'id' => 1, 'username' => puneet, 'mobile' => 0987778987, 'u_id' => 232}
Note:- These all values are separated by space only. Any help will be appreciable.
Thanks in advance
$final_array = array();
$kvps = explode(' ', $attributes);
foreach( $kvps as $kvp ) {
list($k, $v) = explode('=', $kvp);
$final_array[$k] = $v;
}
I can suggest you to do it with a regular expression:
$str = "id=1 username=puneet mobile=0987778987 u_id=232";
$matches = array();
preg_match_all( '/(?P<key>\w+)\=(?P<val>[^\s]+)/', $str, $matches );
$res = array_combine( $matches['key'], $matches['val'] );
working example in phpfiddle
$temp1 = explode(" ", $attributes);
foreach($temp1 as $v){
$temp2 = explode("=", $v);
$attributes[$temp2[0]] = $temp2[1];
}
EXPLODE
this code will solve your problem.
<?php
$attributes = "id=1 username=puneet mobile=0987778987 u_id=232";
$a = explode ( ' ', $attributes) ;
$new_array = array();
foreach($a as $value)
{
//echo $value;
$pos = strrpos($value, "=");
$key = substr($value, 0, $pos);
$value = substr($value, $pos+1);
$new_array[$key] = $value;
}
print_r($new_array);
?>
out put of this code is
Array ( [id] => 1 [username] => puneet [mobile] => 0987778987 [u_id] => 232 )
I think you have to split this string two times
divide with space
divide with '='
I have an source data separated by , but some cases in the its elements contains ,
$A = Array
(
[0] => Array
(
[0] => ",123, abc , company , Inc., 3043, 200, USD",// [123], [abc] , [company , Inc.], [3043], [200], [USD]
[1] => ",456, def , company,Inc., 3043, 200, USD"
)
)
By could not change the data source.( company , Inc., is always fixed array orders )
foreach ($A as $key=>$value){
foreach($value as $k=>$v){
$line = str_replace(',', ';', $v);
$row = explode(',', $line);
list($a, $b, $c, $d, $e, $f) = $row;
}
}
EDIT:
RULE:
yes , the order of company , Inc always fixed and the number of , always 6
$array = explode(',', trim($string, ','));
while (count($array) > 6) {
$array[3] = $array[3] . ',' . $array[4];
unset($array[4]);
$array = array_merge($array);
}
Just a short description: We merge the 3rd and 4th element together, as long as there are more than 6 elements.
Another a little bit more straight forward solution:
$array = explode(',', trim($string, ','));
$result = array_slice($array, 0, 2);
$result[] = implode(',', array_slice($array, 2, - 3));
$result = array_merge($result, array_slice($array, -3));
Made you a simple function that does it. The only reason I create $foo,$bar,$baz is so you can easily use foreach and keep the order.
function parse($str){
$parts=explode(',',$str,4);
$result=array($parts[1],$parts[2]);
$parts=explode(',',$parts[3]);
$foo=array_pop($parts);
$bar=array_pop($parts);
$baz=array_pop($parts);
$result[2]=implode(',',$parts);
$result[3]=$baz;
$result[4]=$bar;
$result[5]=$foo;
return $result;
}
Change the source data to contain quotes around the values, e.g. change it to
[0] => '"123", "abc" , "company , Inc.", "3043", "200", "USD"'
Then use str_getcsv.