Do we have any array function in PHP to get this:
Example:
$array[0] = array("size" => "XL", "color" => "gold");
$array[1] = array("size" => "XLL", "color" => "siver");
$array[2] = array("size" => "M", "color" => "purple");
$color = array();
foreach($arrayas $result)
{
$color[] = $result['color'];
}
I need
$color[0] = "gold";
$color[1] = "silver";
$color[2] = "purple";
Thanks in Advance for your help.
This will do what you're looking for in PHP 5.3+.
$color = array_reduce($array,
function($previous, $new) { $previous[] = $new['color']; return $previous;}
);
If you're on PHP 5.2, you can define a function elsewhere and pass it in:
function getColor($previous, $new) {
$previous[] = $new['color'];
return $previous;
}
$color = array_reduce($array, 'getColor');
Check this out it works fine
$color = array();
foreach($array as $key=>$value)
{
$color[$key] = $value['color'];
}
print_r($color);
Related
I have a string containing an array key position which I am trying to use this position to access the array ($arr).
Example of string ($str) which has a string value of svg.1.linearGradient.0.#style
This would be the equivalent of ['svg'][1]['linearGradient'][0]['#style']
How can I use the string to access/retrieve data from $arr using the above position?
For example, lets say i wanted to unset the array key unset($arr['svg'][1]['linearGradient'][0]['#style']) - how can i achieve this programmatically?
You can use the mechanism of passing the value by reference:
$result = &$arr;
$path = explode('.', $str);
for($i = 0; $i < count($path); $i++) {
$key = $path[$i];
if (is_array($result) && array_key_exists($key, $result)) {
if ($i == count($path) - 1) {
unset($result[$key]); // deleting an element with the last key
} else {
$result = &$result[$key];
}
} else {
break; // not found
}
}
unset($result); // resetting value by reference
print_r($arr);
fiddle
One method could be to split the string on ., then iterate through the "keys" to traverse your $arr object. (Please excuse my poor php, it's been a while...)
Example:
$arr = (object)[
"svg" => (array)[
(object)[],
(object)[
"linearGradient" => [
(object)[
"#style" => "testing",
],
],
],
],
];
$str = "svg.1.linearGradient.0.#style";
$keys = explode('.', $str);
$val = $arr;
foreach($keys as $key) {
$val = is_object($val)
? $val->$key
: $val[$key];
}
echo $val;
https://3v4l.org/h8YPv
Unsetting a key given the path:
$arr = (object)[
"svg" => (array)[
(object)[],
(object)[
"linearGradient" => [
(object)[
"#style" => "testing",
],
],
],
],
];
$str = "svg.1.linearGradient.0.#style";
$keys = explode('.', $str);
$exp = "\$arr";
$val = $arr;
foreach($keys as $index => $key) {
$exp .= is_object($val)
? "->{'" . $key . "'}"
: "[" . $key . "]";
$val = is_object($val) ? $val->$key : $val[$key];
}
eval("unset($exp);");
https://3v4l.org/Fdo6B
Docs
explode()
eval()
I have 2 sets of multidimensional array ($profit & $sales). I want to divide the numbers in 2 multidimensional array to get the % of margin (using this formula: $profit/$sales*100)
$profit= array(
0 => array(
"no"=> "1",
"value"=>"10"
),
1=> array(
"no"=> "2",
"value"=>"15"
)
);
$sales= array(
0 => array(
"no"=> "1",
"value"=>"100"
),
1=> array(
"no"=> "2",
"value"=>"200"
)
);
This is the expected output:
$margin= array(
0 => array(
"no"=> "1",
"value"=>"10"
),
1=> array(
"no"=> "2",
"value"=>"7.5"
)
);
I have done some search with no luck still, below is the function that I'm using, it is not working:
function ArrayDivide($arrayList = [])
{
$m = [];
$no_details = [];
$i = 0;
foreach ($arrayList as $arrayItem) {
foreach ($arrayItem as $subArray) {
if (isset($no_details[$subArray['x']])) {//if no is exist
$m[$no_details[$subArray['x']]]['y'] = $m[$no_details[$subArray['x']]]['y'] /$subArray['y']*100;
} else {
$no_details[$subArray['x']] = $i;
$m[$i] = ["x"=>$subArray['x'], "y"=>"0"];
$i++;
}
}
}
return $m;
}
How you done similar function before? Where should I fix?
Thanks.
Use "Sourcey86" code and replace:
$res = $value / $no;
to
$res = $value/$sales[$key]['value']*100;
(I don't have enough points to add a comment on his post :D )
Something like this ? If I understood your question correctly.
function getMargin($profit, $sales){
$margin = [];
foreach($profit as $key => $val){
$no = $val['no'];
$value = $val['value'];
if(isset($sales[$key]) && $sales[$key]['no'] == $no){
$res = ($value/$sales[$key]['value'])*100;
$margin[$key]['no'] = $no;
$margin[$key]['val'] = $res;
}
}
return $margin;
}
var_dump(getMargin($profit, $sales));
I am trying to created nested array from flat based on its keys.
Also format of keys in original array can be changed if it will simplify task.
From :
$arr = [
'player.name' => 'Joe',
'player.lastName' => 'Snow',
'team.name' => 'Stars',
'team.picture.name' => 'Joe Snow Profile',
'team.picture.file' => 'xxx.jpg'
];
To:
$arr = [
'player' => [
'name' => 'Joe'
, 'lastName' => 'Snow'
]
,'team' => [
'name'=> 'Stars'
,'picture' => [
'name' => 'Joe Snow Profile'
, 'file' =>'xxx.jpg'
]
],
];
Here is my take on it.
It should be able to handle arbitrary depth
function unflatten($arr) {
$result = array();
foreach($arr as $key => $value) {
$keys = explode(".", $key); //potentially other separator
$lastKey = array_pop($keys);
$node = &$result;
foreach($keys as $k) {
if (!array_key_exists($k, $node))
$node[$k] = array();
$node = &$node[$k];
}
$node[$lastKey] = $value;
}
return $result;
}
Combination of iteration and recursion. Could be simplified to just iterative.
$array = [
'player.name' => 'Joe',
'player.lastName' => 'Snow',
'team.name' => 'Stars',
'team.picture.name' => 'Joe Snow Profile',
'team.picture.file' => 'xxx.jpg'
];
$newArray = array ();
foreach($array as $key=> $value) {
$temp = array ();
$keys = array_reverse (explode('.', $key));
$temp[$keys[0]] = $value;
for ($i = 1; $i < count($keys); $i++) {
$temp[$keys[$i]] = $temp;
unset ($temp [$keys [$i -1]]);
}
$newArray = array_merge_recursive($newArray,$temp);
}
var_dump($newArray );
I received this question as a test, this is my answer:
<?php
function buildArray(&$newArray, $keys, $value)
{
if (sizeof($keys) == 0) {
return $value;
} else {
$key = array_shift($keys);
if (isset($newArray[$key])) {
$value = buildArray($newArray[$key], $keys, $value);
if (is_array($value)) {
$newArray[$key] += $value;
} else {
$newArray[$key] = $value;
}
$arr = $newArray;
} else {
$arr[$key] = buildArray($newArray, $keys, $value);
}
}
return $arr;
}
$arr = [
'player.name' => 'Joe',
'player.lastName' => 'Snow',
'team.name' => 'Stars',
'team.picture.name' => 'Joe Snow Profile',
'team.picture.file' => 'xxx.jpg',
];
$newArray = [];
foreach ($arr as $key => $value) {
$explodedKey = explode(".", $key);
$temp = buildArray($newArray, $explodedKey, $value);
$newArray = array_merge($temp, $newArray);
}
print_r($newArray);
?>
You could do it like this
$newArr = [];
for ($arr as $key => $val) {
$tmp = explode ('.', $key);
if (!array_key_exists ($tmp [0], $newArray){
$newArray [$tmp [0]] = [];
}
$newArray [$tmp [0]][$tmp [1]] = $val;
}
edit:
Damn didn't saw the third level in team.
Not very generic but should work for third level ;)
$newArr = [];
for ($arr as $key => $val) {
$tmp = explode ('.', $key);
if (!array_key_exists ($tmp [0], $newArray){
$newArray [$tmp [0]] = [];
}
if (count($tmp) > 2){
if (!array_key_exists ($tmp [1], $newArray[$tmp [0]]){
$newArray [$tmp [0]][$tmp[1]] = [];
}
$newArray [$tmp [0]][$tmp [1]][$tmp [2]] = $val;
} else {
$newArray [$tmp [0]][$tmp [1]] = $val;
}
}
I think you can use something like this, for converting 2d array to nested tree. But You'll have to play with parent_id
https://github.com/denis-cto/flat-array-to-nested-tree
I want to dissect an array like this:
[
"ID",
"UUID",
"pushNotifications.sent",
"campaigns.boundDate",
"campaigns.endDate",
"campaigns.pushMessages.sentDate",
"pushNotifications.tapped"
]
To a format like this:
{
"ID" : 1,
"UUID" : 1,
"pushNotifications" :
{
"sent" : 1,
"tapped" : 1
},
"campaigns" :
{
"boundDate" : 1,
"endDate" : 1,
"pushMessages" :
{
"endDate" : 1
}
}
}
It would be great if I could just set a value on an associative array in a keypath-like manner:
//To achieve this:
$dissected['campaigns']['pushMessages']['sentDate'] = 1;
//By something like this:
$keypath = 'campaigns.pushMessages.sentDate';
$dissected{$keypath} = 1;
How to do this in PHP?
You can use :
$array = [
"ID",
"UUID",
"pushNotifications.sent",
"campaigns.boundDate",
"campaigns.endDate",
"campaigns.pushMessages.sentDate",
"pushNotifications.tapped"
];
// Build Data
$data = array();
foreach($array as $v) {
setValue($data, $v, 1);
}
// Get Value
echo getValue($data, "campaigns.pushMessages.sentDate"); // output 1
Function Used
function setValue(array &$data, $path, $value) {
$temp = &$data;
foreach(explode(".", $path) as $key) {
$temp = &$temp[$key];
}
$temp = $value;
}
function getValue($data, $path) {
$temp = $data;
foreach(explode(".", $path) as $ndx) {
$temp = isset($temp[$ndx]) ? $temp[$ndx] : null;
}
return $temp;
}
function keyset(&$arr, $keypath, $value = NULL)
{
$keys = explode('.', $keypath);
$current = &$arr;
while(count($keys))
{
$key = array_shift($keys);
if(!isset($current[$key]) && count($keys))
{
$current[$key] = array();
}
if(count($keys))
{
$current = &$current[$key];
}
}
$current[$key] = $value;
}
function keyget($arr, $keypath)
{
$keys = explode('.', $keypath);
$current = $arr;
foreach($keys as $key)
{
if(!isset($current[$key]))
{
return NULL;
}
$current = $current[$key];
}
return $current;
}
//Testing code:
$r = array();
header('content-type: text/plain; charset-utf8');
keyset($r, 'this.is.path', 39);
echo keyget($r, 'this.is.path');
var_dump($r);
It's a little rough, I can't guarantee it functions 100%.
Edit: At first you'd be tempted to try to use variable variables, but I've tried that in the past and it doesn't work, so you have to use functions to do it. This works with some limited tests. (And I just added a minor edit to remove an unnecessary array assignment.)
In the meanwhile, I came up with (another) solution:
private function setValueForKeyPath(&$array, $value, $keyPath)
{
$keys = explode(".", $keyPath, 2);
$firstKey = $keys[0];
$remainingKeys = (count($keys) == 2) ? $keys[1] : null;
$isLeaf = ($remainingKeys == null);
if ($isLeaf)
$array[$firstKey] = $value;
else
$this->setValueForKeyPath($array[$firstKey], $value, $remainingKeys);
}
Sorry for the "long" namings, I came from the Objective-C world. :)
So calling this on each keyPath, it actually gives me the output:
fields
Array
(
[0] => ID
[1] => UUID
[2] => pushNotifications.sent
[3] => campaigns.boundDate
[4] => campaigns.endDate
[5] => campaigns.pushMessages.endDate
[6] => pushNotifications.tapped
)
dissectedFields
Array
(
[ID] => 1
[UUID] => 1
[pushNotifications] => Array
(
[sent] => 1
[tapped] => 1
)
[campaigns] => Array
(
[boundDate] => 1
[endDate] => 1
[pushMessages] => Array
(
[endDate] => 1
)
)
)
can someone please explain to me why the first one is working and the second one not? The result is in the second example simply "1".
1.
$c = 0;
$list = array();
foreach ($places as $place) {
$arr = array();
$arr[0] = get_object_vars($place);
$list[$c] = $arr;
$c++;
}
echo json_encode(array("status" => "true", "list" => $list));
2.
$list = array();
foreach ($places as $place) {
array_push($list, get_object_vars($place));
}
echo json_encode(array("status" => "true", "list" => $list));
Sample data for both code samples:
$places = array();
$place = new StdClass;
$place->name = 'first';
$place->location = array('x' => 0.0, 'y' => 0.0);
$places[] = $place;
$place = new StdClass;
$place->name = 'Greenwich Observatory';
$place->location = array('x' => 51.4778, 'y' => 0.0017);
$place->elevation = '65.79m';
$places[] = $place;
In the first case you are adding a key value pair to the array, in the second case just the value. I believe just adding the value SHOULD in fact work, but maybe
foreach ($places as $place) {
array_push($list, array( 0 => get_object_vars($place) );
}
will work better?