A better way to explode twice in PHP - php

Given:
$val = "font-size:12px;color:#ff0000;font-family:Arial";
The following code will explode the string twice, to produce an array of arrays:
$val = explode(';',$val);
foreach($val as &$v)
$v = explode(':',$v);
var_dump($val);
The output is:
array(3) {
[0]=>
array(2) {
[0]=>
string(9) "font-size"
[1]=>
string(4) "12px"
}
[1]=>
array(2) {
[0]=>
string(4) "fill"
[1]=>
string(7) "#ff0000"
}
[2]=>
&array(2) {
[0]=>
string(11) "font-family"
[1]=>
string(5) "Arial"
}
}
Is there a more efficient / cleaner way to achieve the same result?
I'd prefer something with no lambda functions since PHP 5.2 doesn't support them. But this is a purely intellectual question anyway, so, that's just a preference.

You can try with:
$input = "font-size:12px;color:#ff0000;font-family:Arial";
preg_match_all('/([^:]*?):([^;]*);?/', $input, $matches);
$output = array_combine($matches[1], $matches[2]);
Output:
array(3) {
["font-size"]=>
string(4) "12px"
["color"]=>
string(7) "#ff0000"
["font-family"]=>
string(5) "Arial"
}

I'd recommend against references--you can run into some odd errors. But your approach is fine. Alternatively, you could do something with array_map:
$val = array_map(function($v) { return explode(':', $v); }, explode(';', $val)));

Related

String Into Array PHP

I'm trying to convert a string into a multidimentional array.
I've found many answers online but they expect you to have array keys etc...
My String:
UserIds\n234234\n20053\n19928\n16325
I've tried the usual way:
$arr= array();
$arr = explode("\n", $string);
and i've also tried
$arr[] = explode("\n", $string);
but the result is always like this:
array(5) {
[0]=> string(7) "UserIds"
[1]=> string(6) "234234"
[2]=> string(5) "20053"
[3]=> string(5) "19928"
[4]=> string(5) "16325"
}
My Expected Result:
array(5) {
[0]=> array(1) { [0]=> string(7) "UserIds" }
[1]=> array(1) { [0]=> int(234234) }
[2]=> array(1) { [0]=> int(20053) }
[3]=> array(1) { [0]=> int(19928) }
[4]=> array(1) { [0]=> int(16325) }
}
One way to do it could be to map the response using array_map and wrap the items in an array:
$string = "UserIds\n234234\n20053\n19928\n16325";
$arr = array_map(function($x){return [$x];}, explode("\n", $string));
print_r($arr);
Demo

Text file php retrieve

Imagine I have a certain text file like this:-
52 apple, one and teen, 682
How to do I take them like this?
$a['aa']['a1'] - 52
$a['aa']['a2'] - apple
$a['bb']['b1'] - one
$a['bb']['b2'] - and
$a['bb']['b3'] - teen
$a['cc']['c1'] - 682
This reads lines from a file, splits them by comma+space and splits each of those by a space:
<?php
$lines = file($filename);
$foo = array_map(
function($v) {
return array_map(
function($u) {
return explode(" ", $u);
},
explode(", ", trim($v))
);
},
$lines
);
var_dump($foo);
Result:
array(1) {
[0]=>
array(3) {
[0]=>
array(2) {
[0]=>
string(2) "52"
[1]=>
string(5) "apple"
}
[1]=>
array(3) {
[0]=>
string(3) "one"
[1]=>
string(3) "and"
[2]=>
string(4) "teen"
}
[2]=>
array(1) {
[0]=>
string(3) "682"
}
}
}
If you really need specific indices you could handle those in the anonymous functions for each array_map on your own. Right now they're just numerically indexed.

Find matching items in array

Absolutely doing my head in here over something that I'm sure is very simple...
I have 2 arrays.
$post_cats which are categories that any given post is in.
$ad_cats which is an array of categories in which ads are placed.
Basically, if a post has in its array of selected categories, a category that matches an item in the array of ad categories, then it must return the matching value/item.
$post_cats returns this
array(4) {
[0]=> array(1) { ["slug"]=> string(6) "energy" }
[1]=> array(1) { ["slug"]=> string(6) "global" }
[2]=> array(1) { ["slug"]=> string(8) "identify" }
[3]=> array(1) { ["slug"]=> string(5) "south" }
}
and $ad_cats returns this
array(6) {
[0]=> array(1) { ["slug"]=> string(5) "north" }
[1]=> array(1) { ["slug"]=> string(5) "south" }
[2]=> array(1) { ["slug"]=> string(4) "east" }
[3]=> array(1) { ["slug"]=> string(4) "west" }
[4]=> array(1) { ["slug"]=> string(6) "global" }
[5]=> array(1) { ["slug"]=> string(8) "fallback" }
}
The duplicated item there is "south", so in my mind the value of array_intersect($post_cats, $ad_cats); should be an array with a single item - "south", correct?
But its returning, what seems like, everything in either of the arrays... I can't for the life of me get it to work..
Using the above example, I need to return "south" to a variable.
So you are looking for items that are in both arrays? ...
What about something like this:
function find_duplicate($array1, $array2)
{
$list = array();
foreach($array1 as $value1)
{
foreach($array2 as $value2)
{
if($value1 == $value2) $list[] = $value1;
}
}
return $list;
}
The best way is to convert those arrays in arrays array_intersect can work with.
Considering:
$a; // first array
$b; // second array
then you would go with:
$a1 = array();
foreach ($a as $v) $a1[] = $v['slug'];
$b1 = array();
foreach ($b as $v) $b1[] = $v['slug'];
$c = array_intersect($a1, $b1);
PHP functions usually work with more powerful algorithms than what you may think; therefore it's a good choice to let PHP functions handle this kind of things.
This solution uses array_map to get at the values and takes the intersection of that
function mapper($a)
{
return $a['slug'];
}
$set1 = array_map('mapper', $post_cats);
$set2 = array_map('mapper', $ad_cats);
$result = array_intersect($set1, $set2);
PhpFiddle for testing.

Convert number sequence to array in PHP

Kinda of a noobie in PHP and Regex, I receive the following from a web service:
test:002005#1111#333333#;10205#2000#666666#;002005#1111#55555#;
The above line is a sequence of 3 numbers which repeats 3 times. I would like to get the 3rd number of each sequence and I believe the best course (besides 3000 explodes) would be preg_match_all but I am having a tough time wrapping my mind around RegEx.
The end result should look like this:
Array
(
[0] => 333333
[1] => 666666
[2] => 55555
)
Thanks in advance for any help.
if(preg_match_all('/.*?(?:\d+#){2}(\d+)#;/',$s,$m)) {
print_r($m[1]);
}
http://ideone.com/99M9t
or
You can do it using explode as:
$input = rtrim($input,';');
$temp1 = explode(';',$input);
foreach($temp1 as $val1) {
$temp2 = explode('#',$val1);
$result[] = $temp2[2];
}
print_r($result);
http://ideone.com/VH29g
Use the function explode()
<?php
$pizza = "piece1#piece2#piece3#piece4#piece5#piece6";
$pieces = explode("#", $pizza);
echo $pieces[0]; // piece1
echo $pieces[1]; // piece2
?>
I don't remember exactly how the saying goes but...
"You have a problem and decide to use regular expressions... now you have two problems."
Your problem can easily be solved if we assume 'test:' isn't part of the actual string to be parsed.
<?php
$in = '002005#1111#333333#;10205#2000#666666#;002005#1111#55555#;';
function splitGroupsAndGetColumn($input, $groupSeparator, $columnSeparator, $columnIndex, $skipEmpty=true)
{
$result = array();
$groups = explode($groupSeparator, $input);
foreach($groups as $group)
{
$columns = explode($columnSeparator, $group);
if (isset($columns[$columnIndex]))
{
array_push($result, $columns[$columnIndex]);
}
else if (! $skipEmpty)
{
array_push($result, NULL);
}
}
return $result;
}
var_dump(splitGroupsAndGetColumn($in, ';', '#', 2));
Output:
array(3) {
[0]=>
string(6) "333333"
[1]=>
string(6) "666666"
[2]=>
string(5) "55555"
}
You could use preg_match_all for this task, which makes the task quite simple:
$a = "test:002005#1111#333333#;10205#2000#666666#;002005#1111#55555#;";
preg_match_all('/#(\d+)#;/', $a, $m);
print_r($m);
$m[1] contains the output, you want.
Reference: http://php.net/manual/en/function.preg-match-all.php
My version :)
The regex (\d+) means I want all that is a number one or more
php > $a = '002005#1111#333333#;10205#2000#666666#;002005#1111#55555#';
php > preg_match_all('/(\d+)/',$a,$matches);
php > var_dump($matches);
array(2) {
[0]=>
array(9) {
[0]=>
string(6) "002005"
[1]=>
string(4) "1111"
[2]=>
string(6) "333333"
[3]=>
string(5) "10205"
[4]=>
string(4) "2000"
[5]=>
string(6) "666666"
[6]=>
string(6) "002005"
[7]=>
string(4) "1111"
[8]=>
string(5) "55555"
}
[1]=>
array(9) {
[0]=>
string(6) "002005"
[1]=>
string(4) "1111"
[2]=>
string(6) "333333"
[3]=>
string(5) "10205"
[4]=>
string(4) "2000"
[5]=>
string(6) "666666"
[6]=>
string(6) "002005"
[7]=>
string(4) "1111"
[8]=>
string(5) "55555"
}
}

php global trim $_post

Could you trim all $_POST vars? because i have a very long list right now for trim each var. looks very unprofessional. i thought trim($_POST); would maybe work but it didnt :]
you can do this with array_map:
$_POST = array_map('trim', $_POST);
Works with multi-dimensional arrays
array_walk_recursive($_POST, function (&$val)
{
$val = trim($val);
});
foreach($_POST as &$p) $p = trim($p);
Quick and simple:
foreach($_POST as $key => $val)
{
$_POST[$key] = trim($val);
}
The simplest, and cleanest (in my opinion), is to use the built in array_map function:
array_map('trim', $_POST);
You can also apply a method of your own by passing an array as the first callback-parameter like so:
array_map(array('My_Class', 'staticMethod'), $_POST); // Invoke a static method
array_map(array($myObject, 'objectMethod'), $_POST);
// Invoke $myObject->objectMethod for each element of $_POST
Update based on a comment below
Sometimes the $_POST array may contain arrays. If you want to trim contents of those arrays as well, there are many custom implementations of array_map_recursive available in the PHP manual user notes. Go there and choose one for yourself. If you don't like to take a custom implementation, array_walk_recursive is also a good option for you.
You can do this with array_walk().
Using recursive function you can do that.
PHP
// Static $_POST Array.
$_POST['1']='one ';
$_POST['2']=' two';
$_POST['3'][]=' three ';
$_POST['4'][][]=' four';
$_POST['5'][0][1][3]='five ';
// Recursive function for trim data.
function trim_recursive($array){
$return = array();
foreach($array as $key=>$values){
if(is_array($values)===true){
$return[$key] = trim_recursive($values);
}
else{
$return[$key] = trim($values);
}
}
return $return;
}
// Usage.
$_POST = trim_recursive($_POST);
Output
// Output before trim.
array(5) {
[1]=>
string(4) "one "
[2]=>
string(4) " two"
[3]=>
array(1) {
[0]=>
string(9) " three "
}
[4]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(5) " four"
}
}
[5]=>
array(1) {
[0]=>
array(1) {
[1]=>
array(1) {
[3]=>
string(5) "five "
}
}
}
}
// Output after trim.
array(5) {
[1]=>
string(3) "one"
[2]=>
string(3) "two"
[3]=>
array(1) {
[0]=>
string(5) "three"
}
[4]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(4) "four"
}
}
[5]=>
array(1) {
[0]=>
array(1) {
[1]=>
array(1) {
[3]=>
string(4) "five"
}
}
}
}

Categories