Convert array values to an array - php

I can't figure out how to effectively convert the values of this array from a string to array. I really appreciate any suggestion.
array(6) {
["A"]=>
string(31) "['B' => 3, 'C' => 5, 'D' => 9],"
["B"]=>
string(41) "['A' => 3, 'C' => 3, 'D' => 4, 'E' => 7],"
["C"]=>
string(51) "['A' => 5, 'B' => 3, 'D' => 2, 'E' => 6, 'F' => 3],"
["D"]=>
string(51) "['A' => 9, 'B' => 4, 'C' => 2, 'E' => 2, 'F' => 2],"
["E"]=>
string(41) "['B' => 7, 'C' => 6, 'D' => 2, 'F' => 5],"
["F"]=>
string(31) "['C' => 3, 'D' => 2, 'E' => 5],"
}
Desired output:
$graph = [
'A' => ['B' => 3, 'C' => 5, 'D' => 9],
'B' => ['A' => 3, 'C' => 3, 'D' => 4, 'E' => 7],
'C' => ['A' => 5, 'B' => 3, 'D' => 2, 'E' => 6, 'F' => 3],
'D' => ['A' => 9, 'B' => 4, 'C' => 2, 'E' => 2, 'F' => 2],
'E' => ['B' => 7, 'C' => 6, 'D' => 2, 'F' => 5],
'F' => ['C' => 3, 'D' => 2, 'E' => 5],
];

Seems like you're trying to convert array string to an array.
You can repeat through loop or make function to get your desired output.
I'm using regular expression with preg_match_all
Code
$rawArray = array("A"=>"['B' => 3, 'C' => 5, 'D' => 9],",
"B"=>"['A' => 3, 'C' => 3, 'D' => 4, 'E' => 7],",
"C"=>"['A' => 5, 'B' => 3, 'D' => 2, 'E' => 6, 'F' => 3],",
"D"=>"['A' => 9, 'B' => 4, 'C' => 2, 'E' => 2, 'F' => 2],",
"E"=>"['B' => 7, 'C' => 6, 'D' => 2, 'F' => 5],",
"F"=>"['C' => 3, 'D' => 2, 'E' => 5],",
);
foreach($rawArray as $k => $v){
preg_match_all("/\'(.)\'/", $v, $key);
preg_match_all("/=> (\d)/", $v, $val);
$graph[$k] = array_combine($key[1], $val[1]);
}
print_r($graph);
Output
Array
(
[A] => Array
(
[B] => 3
[C] => 5
[D] => 9
)
[B] => Array
(
[A] => 3
[C] => 3
[D] => 4
[E] => 7
)
[C] => Array
(
[A] => 5
[B] => 3
[D] => 2
[E] => 6
[F] => 3
)
[D] => Array
(
[A] => 9
[B] => 4
[C] => 2
[E] => 2
[F] => 2
)
[E] => Array
(
[B] => 7
[C] => 6
[D] => 2
[F] => 5
)
[F] => Array
(
[C] => 3
[D] => 2
[E] => 5
)
)
Live demo
Explanation:
$rawArray is associate array, each of it's element contain string similar to php array.
We're looping through array and converting that string to array by using preg_match_all and building $graph multidimension array.
When loop execute first time $k is equal to A and $v is equal to ['B' => 3, 'C' => 5, 'D' => 9],
First preg_match_all make array of keys from $v (['B' => 3, 'C' => 5, 'D' => 9],), and assign it to $key[1]. Now $key[1] is array ['B', 'C', 'D'].
Second preg_match_all make array of values from $v (['B' => 3, 'C' => 5, 'D' => 9],), and assign it to $val[1]. Now $val[1] is array [2, 5, 9].
We're combining$key[1]as keys and $val[1] as values by using array_combine to the $graph[$k] where $k is A.
How preg_match_all works?
preg_match_all($pattern, $string, $out);
It's matches pattern from string and then assign result to the $out as array.
Learn more about.
preg_match_all
regex pattern cheat sheet
Note: We're using non-capturing pattern so, it's return both exact match and desired match... So our desired record found in$key[1].

This is how you can do it,
<?php
$graph = array("A"=>"['B' => 3, 'C' => 5, 'D' => 9],",
"B"=>"['A' => 3, 'C' => 3, 'D' => 4, 'E' => 7],",
"C"=>"['A' => 5, 'B' => 3, 'D' => 2, 'E' => 6, 'F' => 3],",
"D"=>"['A' => 9, 'B' => 4, 'C' => 2, 'E' => 2, 'F' => 2],",
"E"=>"['B' => 7, 'C' => 6, 'D' => 2, 'F' => 5],",
"F"=>"['C' => 3, 'D' => 2, 'E' => 5],",
);
foreach ($graph as $key => $value) {
$val = str_replace("[","{",$value);
$val = str_replace("]","}",$val);
$val = str_replace("'",'"',$val);
$val = str_replace("=>",":",$val);
$val = rtrim($val, ',');
$graph[$key] = json_decode($val, true);
}
echo "<pre>";
print_r($graph);
echo "</pre>";
Output
Array
(
[A] => Array
(
[B] => 3
[C] => 5
[D] => 9
)
[B] => Array
(
[A] => 3
[C] => 3
[D] => 4
[E] => 7
)
[C] => Array
(
[A] => 5
[B] => 3
[D] => 2
[E] => 6
[F] => 3
)
[D] => Array
(
[A] => 9
[B] => 4
[C] => 2
[E] => 2
[F] => 2
)
[E] => Array
(
[B] => 7
[C] => 6
[D] => 2
[F] => 5
)
[F] => Array
(
[C] => 3
[D] => 2
[E] => 5
)
)

A little ugly but I think this finally does the trick.
I downloaded your file and ran this locally so that the source is exactly as you stated. Then I proceeded to parse it and convert the string value to an actual array
Here's how it looks now:
// Parse graph.json file
$json = json_decode(file_get_contents('graph.json'), true);
foreach ($json as $key => $value) {
foreach ($value as $k => $val) {
$str = str_replace(['[', ']'], '', $val);
$str = str_replace(' => ', ',', $str);
$str = str_replace("'", "", $str);
$str = explode(',', $str);
for ($x = 0; $x < count($str); $x = $x + 2) {
$graph[$k][trim($str[$x])] = $str[$x+1];
}
}
}
// Result
echo "<pre>";
print_r($graph);
// Proof it is an array now (result 3)
// echo '<pre>';
// print_r($graph['A']['B']);
Final Result:
Array
(
[A] => Array
(
[B] => 3
[C] => 5
[D] => 9
)
[B] => Array
(
[A] => 3
[C] => 3
[D] => 4
[E] => 7
)
[C] => Array
(
[A] => 5
[B] => 3
[D] => 2
[E] => 6
[F] => 3
)
[D] => Array
(
[A] => 9
[B] => 4
[C] => 2
[E] => 2
[F] => 2
)
[E] => Array
(
[B] => 7
[C] => 6
[D] => 2
[F] => 5
)
[F] => Array
(
[C] => 3
[D] => 2
[E] => 5
)
)
If you run the below which is your expected output example and then compare the output to my output it is identical:
$graph = [
'A' => ['B' => 3, 'C' => 5, 'D' => 9],
'B' => ['A' => 3, 'C' => 3, 'D' => 4, 'E' => 7],
'C' => ['A' => 5, 'B' => 3, 'D' => 2, 'E' => 6, 'F' => 3],
'D' => ['A' => 9, 'B' => 4, 'C' => 2, 'E' => 2, 'F' => 2],
'E' => ['B' => 7, 'C' => 6, 'D' => 2, 'F' => 5],
'F' => ['C' => 3, 'D' => 2, 'E' => 5],
];
echo '<pre>';
print_r($graph);

The proper answer is: don't create such a strange array ;) But since you did, this should do the trick:
//or $graph instead of $result
$result = array_map(function($value) {
//use eval to directly evaluate the string
//we just need to remove the trailing comma
//and add a semicolon
eval('$ret = '.rtrim($value,',').';');
return($ret);
}, $array); // replace $array with the var name of your array!
But remember: eval is evil. If you don't trust the input you need to write your own parser.
Temporary edit for clarification. This is what I get when I run your github example trough json_decode(...,true):
array(6) {
[0]=>
array(1) {
["A"]=>
string(30) "['B' => 3, 'C' => 5, 'D' => 9]"
}
[1]=>
array(1) {
["B"]=>
string(40) "['A' => 3, 'C' => 3, 'D' => 4, 'E' => 7]"
}
[2]=>
array(1) {
["C"]=>
string(50) "['A' => 5, 'B' => 3, 'D' => 2, 'E' => 6, 'F' => 3]"
}
[3]=>
array(1) {
["D"]=>
string(50) "['A' => 9, 'B' => 4, 'C' => 2, 'E' => 2, 'F' => 2]"
}
[4]=>
array(1) {
["E"]=>
string(40) "['B' => 7, 'C' => 6, 'D' => 2, 'F' => 5]"
}
[5]=>
array(1) {
["F"]=>
string(30) "['C' => 3, 'D' => 2, 'E' => 5]"
}
}
This differs from your question.

Related

Comparing two arrays php with a third array

I have two arrays with the year's results.
array A (
[a] => '150'
[b] => '200'
[c] => '300'
[d] => '1000'
[e] => '350'
[f] => '1000'
)
array B (
[a] => '500'
[b] => '400'
[d] => '1000'
[f] => '1000'
)
I need to compare the growth results between the two building another array, to show it in a html table. Ex:
[a] => 233%
[b] => 100%
...
I have a array identifying the indexes that are not present on array b.
array c = ('c', 'e');
The thing is, I need the row C and E to still be displayed on the table. But on the iteration, how can i just jump the line with this indexes that have 0 value avoiding calculation 300 by 0 and putting a message instead?
You can iterate the first array and check the next one values:
$arrayA = [
'a' => '150',
'b' => '200',
'c' => '300',
'd' => '1000',
'e' => '350',
'f' => '1000',
];
$arrayB = [
'a' => '500',
'b' => '400',
'd' => '1000',
'f' => '1000',
];
$result = [];
foreach ($arrayA as $key => $value) {
if(isset($arrayB[$key])) {
$result[$key] = round($arrayB[$key] * 100 / $value, 2);
} else {
$result[$key] = 'some value when empty';
}
}
var_dump($result);
Output:
array(6) {
["a"]=>
float(333.33)
["b"]=>
float(200)
["c"]=>
string(21) "some value when empty"
["d"]=>
float(100)
["e"]=>
string(21) "some value when empty"
["f"]=>
float(100)
}
You could loop through array A and check if the key of array A exists in array B using array_key_exists and then calculate the growth percentage:
$arrayA = [
'a' => '150',
'b' => '200',
'c' => '300',
'd' => '1000',
'e' => '350',
'f' => '1000'
];
$arrayB = [
'a' => '500',
'b' => '400',
'd' => '1000',
'f' => '1000'
];
$arrayC = [];
foreach($arrayA as $keyA => $valueA) {
if (array_key_exists($keyA, $arrayB)) {
$arrayC[$keyA] = floor((($arrayB[$keyA] - $valueA) / $valueA ) * 100) . "%";
continue;
}
$arrayC[$keyA] = "No match";
}
Result
Array
(
[a] => 233%
[b] => 100%
[c] => No match
[d] => 0%
[e] => No match
[f] => 0%
)
Demo
If you want a more flexible solution where you can check for both values of the two arrays (i.e. do not base the comparison keys on a single array) and have the possibility to expand it for more than two arrays (it may be useful to others who do not have your same goal).
Fetch the keys of the two array with array_keys and use array_unique in order to avoid duplicate keys values.
<?php
$array_a = [
'a' => 150,
'b' => 200,
'c' => 300,
'd' => 1000,
'e' => 350,
'f' => 1000
];
$array_b = [
'a' => 500,
'b' => 400,
'd' => 1000,
'f' => 1000
];
$keys_a = array_keys($array_a);
$keys_b = array_keys($array_b);
$keys = array_unique(array_merge($keys_a, $keys_b));
$result = [];
foreach ($keys as $key)
{
if (isset($array_a[$key]) && isset($array_b[$key]))
{
$result[$key] = round((($array_b[$key] - $array_a[$key]) / $array_a[$key]) * 100);
}
else
{
$result[$key] = "missing key in one of the two arrays";
}
}
Output:
Array
(
[a] => 233
[b] => 100
[c] => missing key in one of the two arrays
[d] => 0
[e] => missing key in one of the two arrays
[f] => 0
)

PHP array sorting not working as expected

Below is an output of my array
$array1 = Array ( [d] => 5 [e] => 1 [a] => 3 [b] => 3 [c] => 3 [f] => 3 )
I want to sort it like...
Array ( [d] => 5 [a] => 3 [b] => 3 [c] => 3 [f] => 3 [e] => 1)
I am using arsort($array1)
which results in var_dump($array1)
array (size=6)
'd' => int 5
'f' => int 3
'c' => int 3
'a' => int 3
'b' => int 3
'e' => int 1
anyways to fix this?
Try this :
$array1 = [
'd' => 5,
'e' => 1,
'a' => 3,
'b' => 3,
'c' => 3,
'f' => 3
];
array_multisort(array_values($array1), SORT_DESC, array_keys($array1), SORT_ASC, $array1);
print_r($array1);
Here first array_values($array1), SORT_DESC will sort the values in descending order and then array_keys($array1), SORT_ASC will sort the keys into ascending order and finally both the thing applies to the main array i.e. $array1.
O/P - Array ( [d] => 5 [a] => 3 [b] => 3 [c] => 3 [f] => 3 [e] => 1 )
I hope this time I get what you want. Finger crossed !!!
you can work like this its working.
<?php
$array1 = array( "[d]" => 5,"[e]" => 1,"[a]" => 3,"[b]" => 3,"[c]" => 3,"[f]" => 3 );
$a = arsort($array1);
foreach($array1 as $x => $x_value) {
echo "Key=" . $x . ", Value=" . $x_value;
echo "<br>";
}
?>
output:
Key=[d], Value=5
Key=[f], Value=3
Key=[c], Value=3
Key=[a], Value=3
Key=[b], Value=3
Key=[e], Value=1
You can use uasort for this.
$array = array('d' => 5, 'e' => 1, 'a' => 3, 'b' => 3, 'c' => 3, 'f' => 3);
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a > $b) ? -1 : 1;
}
uasort($array, 'cmp');
print_r($array);
I tested the code and surely it will work for you.

Inline array concatenation?

Is it possible to concatenate an array using inline code (i.e. inside the array declaration)?
For instance:
function get_array() {
return array('four' => 4, 'five' => 5);
}
$arr = array(
'one' => 1,
'two' => 2,
'three' => 3,
get_array()
);
var_dump($arr);
will result in:
Array(
[one] => 1
[two] => 2
[three] => 3
[0] => Array(
[four] => 4
[five] => 5
)
)
Whereas the desired result would be:
Array(
[one] => 1
[two] => 2
[three] => 3
[four] => 4
[five] => 5
)
Use array_merge(). It is an extra step but since you can't do this during the array declaration it is the next best thing.
$new_array = array_merge($arr, array('four' => 4, 'five' => 5));
print_r($new_array);
Array ( [one] => 1 [two] => 2 [three] => 3 [four] => 4 [five] => 5 )
See it in action

How to merge array and preserve keys?

I have two arrays:
$array1 = array('a' => 1, 'b' => 2, 'c' => 3);
$array2 = array('d' => 4, 'e' => 5, 'f' => 6, 'a' => 'new value', '123' => 456);
I want to merge them and keep the keys and the order and not re-index!!
How to get like this?
Array
(
[a] => new value
[b] => 2
[c] => 3
[d] => 4
[e] => 5
[f] => 6
[123] => 456
)
I try to array_merge() but it will not be preserved the keys:
print_r(array_merge($array1, $array2));
Array
(
[a] => 'new value'
[b] => 2
[c] => 3
[d] => 4
[e] => 5
[f] => 6
[0] => 456
)
I try to the union operator but it will not overwriting that element:
print_r($array1 + $array2);
Array
(
[a] => 1 <-- not overwriting
[b] => 2
[c] => 3
[d] => 4
[e] => 5
[f] => 6
[123] => 456
)
I try to swapped place but the order is wrong, not my need:
print_r($array2 + $array1);
Array
(
[d] => 4
[e] => 5
[f] => 6
[a] => new value
[123] => 456
[b] => 2
[c] => 3
)
I dont want to use a loop, is there a way for high performance?
You're looking for array_replace():
$array1 = array('a' => 1, 'b' => 2, 'c' => 3);
$array2 = array('d' => 4, 'e' => 5, 'f' => 6, 'a' => 'new value', '123' => 456);
print_r(array_replace($array1, $array2));
Available since PHP 5.3.
Update
You can also use the union array operator; it works for older versions and might actually be faster too:
print_r($array2 + $array1);
Let suppose we have 3 arrays as below.
$a = array(0=>['label'=>'Monday','is_open'=>1],1=>['label'=>'Tuesday','is_open'=>0]);
$b = array(0=>['open_time'=>'10:00'],1=>['open_time'=>'12:00']);
$c = array(0=>['close_time'=>'18:00'],1=>['close_time'=>'22:00']);
Now, if you want to merge all these array and want a final array that have all array's data under key 0 in 0 and 1 in 1 key as so on.
Then you need to use array_replace_recursive PHP function, as below.
$final_arr = array_replace_recursive($a, $b , $c);
The result of this will be as below.
Array
(
[0] => Array
(
[label] => Monday
[is_open] => 1
[open_time] => 10:00
[close_time] => 18:00
)
[1] => Array
(
[label] => Tuesday
[is_open] => 0
[open_time] => 12:00
[close_time] => 22:00
)
)
Hope the solution above, will best fit your requirement!!
#Jack uncovered the native function that would do this but since it is only available in php 5.3 and above this should work to emulate this functionality on pre 5.3 installs
if(!function_exists("array_replace")){
function array_replace(){
$args = func_get_args();
$ret = array_shift($args);
foreach($args as $arg){
foreach($arg as $k=>$v){
$ret[(string)$k] = $v;
}
}
return $ret;
}
}
array_replace_recursive() or array_replace() is the function you are looking for
$array1 = array('a' => 1, 'b' => 2, 'c' => 3);
$array2 = array('d' => 4, 'e' => 5, 'f' => 6, 'a' => 'new value', '123' => 456);
var_dump(array_replace_recursive($array1, $array2));
Demo
I think this might help if i understand properly:
foreach ($i = 0, $num = count($array2); $i < $num; $i++)
{
$array = array_merge($array1, $arrar2[$i]);
}

sorting an array with unsorted index

i got an array like this with unsorted outer index.
$a = array(
(1) => array(1, 2, 3, 0, 5, 4),
(0) => array(2, 1, 5, 0, 3, 4)
);
echo "<br/>Before Sorting: ";
print_r($a);
foreach($a as $b)
array_multisort($b, SORT_ASC, SORT_NUMERIC);
echo "<br/>After Sorting: ";
print_r($a);
which gives me output as below
Before Sorting:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
[4] => 5
[5] => 4
)
[0] => Array
(
[0] => 2
[1] => 1
[2] => 5
[3] => 0
[4] => 3
[5] => 4
)
)
After Sorting:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
[4] => 5
[5] => 4
)
[0] => Array
(
[0] => 2
[1] => 1
[2] => 5
[3] => 0
[4] => 3
[5] => 4
)
)
AND WHAT I WANT IS
$a = array(
(0) => array(2, 1, 5, 0, 3, 4),
(1) => array(1, 2, 3, 0, 5, 4)
);
please tell me how to deal with.........
How about just using ksort (as you need to reorder your array by key)?
$a = array(
1 => array(1, 2, 3, 0, 5, 4),
0 => array(2, 1, 5, 0, 3, 4)
);
echo "<br/>Before Sorting: ";
print_r($a);
ksort($a);
echo "<br/>After Sorting: ";
print_r($a);
Since you're only wanting to sort by the top level indices, you don't need to use multisort. You don't even need a loop.
Try this:
$a = array(
(1) => array(1, 2, 3, 0, 5, 4),
(0) => array(2, 1, 5, 0, 3, 4)
);
ksort($a);
print_r($a);
Should give you what you want.
See http://www.php.net/manual/en/function.ksort.php for more info.

Categories