This question already has answers here:
How to access and manipulate multi-dimensional array by key names / path?
(10 answers)
Closed 6 years ago.
Let's assume that I have an array like following:
$settings = array(
"age" => "25",
"data" => array(
"name" => "John Dewey",
"zip_code" => "00000"
)
);
Here's my input:
$target_directory = "data.name"; // targets $settings["data"]["name"]
$new_value = "Micheal"; // I want to change
// $settings["data"]["name"] with this value
I want something similar to following:
$new_array = dont_know_what_to_do($target_directory, $new_value, $settings);
A print_r($new_array) should return following:
Array
(
[age] => 25
[data] => Array
(
[name] => Micheal,
"zip_code" => "00000"
)
)
The change should be totally dynamic, meaning that data.zip_code = "98985" should also change only the zip code value from 00000 to 98985, and so on...
Here is the dynamic set funciton, you can use it set any depth. Demo here for you question.
function set($settings, $target_directory, $new_value)
{
$array = explode('.', $target_directory);
$ref = &$settings;
while($v = current($array))
{
$ref = &$ref[$v];
next($array);
}
$ref = $new_value;
return $settings;
}
$settings = array(
"age" => "25",
"data" => array(
"name" => "John Dewey",
"zip_code" => "00000"
)
);
$new_value = "Micheal";
$settings["data"]["name"] = $new_value;
print_r($settings);
//In your main function
public function something() {
$settings = array(
"age" => "25",
"data" => array(
"name" => "John Dewey",
"zip_code" => "00000"
)
);
$target = 'data.name';
$input = 'Other Name'
$new_arr = dont_know_what_to_do($target_dir, $input);
print_r($new_arr);
}
//Create new function
public function dont_know_what_to_do($settings, $target, $input) {
$key = explode('.', $target)
return $settings['data'][$key[1]] = $input;
}
Related
I have this function, where a array_filter function is included:
$var = "test";
function mainFunction() {
global $var;
$myNewArray = array();
$data = array("a", "b", "c");
array_filter($data, function ($value) {
global $myNewArray;
$myNewArray[] = $value;
});
print_r($myNewArray); // TEST OUTPUT
}
mainFunction();
Problem:
My test output myNewArray is empty.
I know that my array_filter function is senless at the moment until I check no values.
But only for testing, I would like to use it, to create a newArray. But this doesn't work. Where is my mistake?
UPDATE
I updated my code:
function mainFunction() {
global $var;
$myNewArray = array();
$data[] = array("id" => "1", "content" => "Hello");
$data[] = array("id" => "2", "content" => "World");
$myNewArray = array_filter($data, function ($value) {
if ($value['content'] == "World") {
return $value['content'];
}
});
print_r($myNewArray); // TEST OUTPUT
}
mainFunction();
This works, but not correctly.
I would like to save only the content value.
But my $myNewArray looks like this:
Array
(
[0] => Array
(
[id] => 2
[content] => World
)
)
Instead of
Array
(
[0] => Array
(
[content] => World
)
)
I would combine array_filter and array_map for this.
$data[] = array("id" => "1", "content" => "Hello");
$data[] = array("id" => "2", "content" => "World");
// filter the data
$data = array_filter($data, fn ($value) => $value['content'] === 'World');
// map the data
$data = array_map(fn ($value) => ['content' => $value['content']], $data);
// reset indexes
$data = array_values($data);
print_r($data);
Example: https://phpize.online/s/9U
Everything seems to work fine.
<?php
$data = [];
$data[] = array("id" => "1", "content" => "Hello");
$data[] = array("id" => "2", "content" => "World");
$filtered_data = array_filter($data, function($value) {
return $value['content'] == "World";
});
print_r($filtered_data);
The output is just like expected:
Array (
[1] => Array
(
[id] => 2
[content] => World
)
)
But if you want to leave only some fields in resulting array, array_filter will not help you (at least without a crutch).
You may want to iterate source array and filter it by yourself.
<?php
$data = [];
$data[] = array("id" => "1", "content" => "Hello");
$data[] = array("id" => "2", "content" => "World");
$filtered_data = [];
foreach($data as $v) {
if($v['content'] == "World")
$filtered_data[] = ["content" => $v['content']];
}
print_r($filtered_data);
The output then would be:
Array (
[0] => Array
(
[content] => World
)
)
You want two different things :
filter your array (keep only some elements)
map your array (change the value of each element)
Filter your array
On your second attempt you've done it right but array_filter callback function expect a boolean as the return value. It will determine wherever array_filter need to keep the value or not.
Map your array
You need to remove all value on each element except the "content" value. You can use array_map to do that.
function mainFunction() {
$data[] = array("id" => "1", "content" => "Hello");
$data[] = array("id" => "2", "content" => "World");
$myNewArray = array_filter($data, function ($value) {
if ($value['content'] == 'World') {
return true;
}
return false;
});
// myNewArray contains now the willing elements, but still don't have the willing format
/* myNewArray is [
0 => [
'id' => '2',
'content' => 'World'
]
]*/
$myNewArray = array_map($myNewArray, function($value){
return [
'content' => $value['content']
];
});
// myNewArray contains now the willing elements with the willing format
/* myNewArray is [
0 => [
'content' => 'World'
]
] */
}
mainFunction();
In mainFunction you are not using $myNewArray as global so it's only in the scope, but in the array_filter function you are using global $myNewArray;
$var = "test";
$myNewArray; // global array
function mainFunction() {
global $var, $myNewArray;//if this is not present it's not global $myNewArray
$myNewArray = array();
$data = array("a", "b", "c");
array_filter($data, function ($value) {
global $myNewArray;//this uses global
$myNewArray[] = $value;
});
print_r($myNewArray); // TEST OUTPUT
}
mainFunction();
Here is an example of you code without global $myNewArray
$var = "test";
function mainFunction($var) {
$myNewArray = array();
$data = array("a", "b", "c");
$myNewArray[] = array_filter($data, function ($value) {
return $value;
});
print_r($myNewArray); // TEST OUTPUT
}
mainFunction($var);
Answer to Update:
You can use array_reduce to achieve that
function mainFunction() {
global $var;
$myNewArray = array();
$data[] = array("id" => "1", "content" => "Hello");
$data[] = array("id" => "2", "content" => "World");
$myNewArray = array_reduce($data, function($accumulator, $item) {
if ($item['content'] === "World")
$accumulator[] = ['content' => $item['content']];
return $accumulator;
});
print_r($myNewArray); // TEST OUTPUT
}
mainFunction();
you can use this code..........
<?php
function test_odd($var)
{
return($var & 1);
}
$a1=array(1,3,2,3,4);
print_r(array_filter($a1,"test_odd"));
?>
Please find below the code sample for adding repeated values inside inner array. Can anyone suggest an alternative way to add the values faster? The code will work with smaller arrays, but I want to add big arrays that contain huge amount of data. Also I want to increase execution time.
<?php
$testArry = array();
$testArry[0] = array(
"text" => "AB",
"count" => 2
);
$testArry[1] = array(
"text" => "AB",
"count" => 5
);
$testArry[2] = array(
"text" => "BC",
"count" => 1
);
$testArry[3] = array(
"text" => "BD",
"count" => 1
);
$testArry[4] = array(
"text" => "BC",
"count" => 7
);
$testArry[5] = array(
"text" => "AB",
"count" => 6
);
$testArry[6] = array(
"text" => "AB",
"count" => 2
);
$testArry[7] = array(
"text" => "BD",
"count" => 111
);
$match_key = array();
$final = array();
foreach ($testArry as $current_key => $current_array) {
$match_key = array();
foreach ($testArry as $search_key => $search_array) {
$key = '';
if ($search_array['text'] == $current_array['text']) {
$match_key[] = $search_key;
$key = $search_array['text'];
if (isset($final[$key])) {
$final[$key] += $search_array['count'];
} else {
$final[$key] = $search_array['count'];
}
}
}
for ($j = 0; $j < count($match_key); $j++) {
unset($testArry[$match_key[$j]]);
}
}
print_r($final);
?>
Anyway to add memory during the execution time?
Thank you.
One array_walk will be enough to solve your problem,
$final = [];
array_walk($testArry, function($item) use(&$final){
$final[$item['text']] = (!empty($final[$item['text']]) ? $final[$item['text']] : 0) + $item['count'];
});
print_r($final);
Output
Array
(
[AB] => 15
[BC] => 8
[BD] => 112
)
Demo
array_walk — Apply a user supplied function to every member of an array
array_map() - Applies the callback to the elements of the given arrays
array_key_exists() - Checks if the given key or index exists in the array
You can use array_walk and array_key_exists to iterate through the array element and sum the one which has text index same
$res = [];
array_map(function($v) use (&$res){
array_key_exists($v['text'], $res) ? ($res[$v['text']] += $v['count']) : ($res[$v['text']] = $v['count']);
}, $testArry);
I have to create a array dynamically like I have a method which will pass keys and based on those keys I need to create arrays inside them
Format will be like-
{
"TEST1":{
"140724":[
{
"A":"1107",
"B":4444,
"C":"1129",
"D":"1129"
},
{
"A":"1010",
"B":2589,
"C":"1040",
"D":"1040"
}
],
"140725":[
]
}
}
So how should I frame this logic inside for loop. I am new to php so formatting the same creating trouble.
$json_Created = array("TEST1" => array());
foreach($val as $key=>$value){
array_push($json_created,array($key = array()));
}
The entire array is dynamic, so like I have 140724 ,,, till 140731 (actually date format yymmdd), any amount if numbers can be considered. SO that part is dynamic moreover some dates may be wont have any values and some will have.
So my main point is to develop that logic so that irrespective the
number of inputs , my array formation must be intact.
You can use json_encode with array to do so
$array = array(
"TEST1" => array(
"140724" => array(
array(
"A" => "1107",
"B" => "4444",
"C" => "1129",
"D" => "1129"
),
array (
"A" => "1010",
"B" => "2589",
"C" => "1040",
"D" => "1040"
)
),
"140725" => array(
)
)
);
echo json_encode($array);
Another way to construct array is
$array = array();
$array["TEST1"]["140724"][] = array(
"A" => "1107",
"B" => "4444",
"C" => "1129",
"D" => "1129"
);
$array["TEST1"]["140724"][] = array (
"A" => "1010",
"B" => "2589",
"C" => "1040",
"D" => "1040"
);
$array["TEST1"]["140725"] = array();
echo json_encode($array);
Finally managed to write the code-
$keys_content = array("starttime", "id", "duration", "endtime");
$dates = array();//140724,140725,140726140727
$mainID =“TEST1”;
$arraySuperMain = array();
$arrayMain = array();
for ($j = 0; $j < count($dates); $j++) {
$array_main = array();
$subset = array();
for ($i = 0; $i < count($keys_content); $i++) {
$key = $keys_content[$i];
$subset = array_push_assoc($subset, $key, "Value".$i);
}
$array_main = array_push_assoc($array_main, $dates[$j], $subset);
array_push($arrayMain, $array_main);
}
$createdJSON = array_push_assoc($arraySuperMain, $mainID, $arrayMain);
public static function array_push_assoc($array, $key, $value) {
$array[$key] = $value;
return $array;
}
This question already has answers here:
Is there a function to extract a 'column' from an array in PHP?
(15 answers)
Closed 5 months ago.
This is more a request for a quick piece of advice as, I find it very hard to believe there isn't a native function for the task at hand. Consider the following:
array =>
(0) => array("id" => "1", "groupname" => "fudge", "etc" => "lorem ipsum"),
(1) => array("id" => "2", "groupname" => "toffee", "etc" => "lorem ipsum"),
(2) => array("id" => "3", "groupname" => "caramel", "etc" => "lorem ipsum")
)
What I am looking to get is a new array which uses only "groupname" so would equal:
array =>
(0) => "fudge",
(1) => "toffee",
(2) => "caramel"
)
I know this is very simple to achieve recursively going through the original array, but I was wondering if there is a much simpler way to achieve the end result. I've looked around the internet and on the PHP manual and can't find anything
Thank you kindly for reading this question
Simon
There is a native array_column() function exactly for this (since PHP 5.5):
$column = array_column($arr, 'groupname');
If you are using PHP 5.3, you can use array_map [docs] like this:
$newArray = array_map(function($value) {
return $value['groupname'];
}, $array);
Otherwise create a normal function an pass its name (see the documentation).
Another solution is to just iterate over the array:
$newArray = array();
foreach($array as $value) {
$newArray[] = $value['groupname'];
}
You definitely don't have to use recursion.
Use array_map:
<?php
$a = array(
array("id" => "1", "groupname" => "fudge", "etc" => "lorem ipsum"),
array("id" => "2", "groupname" => "toffee", "etc" => "lorem ipsum"),
array("id" => "3", "groupname" => "caramel", "etc" => "lorem ipsum")
);
function get_groupname( $arr )
{
return $arr['groupname'];
}
$b = array_map( 'get_groupname', $a );
var_dump( $a );
var_dump( $b );
http://codepad.org/7kNi8nNm
Values by all array keys:
$array = [
["id"=>"1","user"=>"Ivan"],
["id"=>"2","user"=>"Ivan"],
["id"=>"3","user"=>"Elena"]
];
$res = [];
$array_separate = function($value, $key) use (&$res){
foreach($value AS $k=>$v) {
$res[$k][] = $v;
}
};
array_walk($array, $array_separate);
print_r($res);
result:
Array
(
[id] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[user] => Array
(
[0] => Ivan
[1] => Ivan
[2] => Elena
)
)
http://sandbox.onlinephpfunctions.com/code/3a8f443283836468d8dc232ae8cc8d11827a5355
As far as I know there isn't a simple function in PHP that could handle this for you, the array structure is user-defined, you would have to loop through the array. The easiest way I can think of would be something like this:
for($i = 0;$i < count($main_array);$i++){
$groupname_array[] = $main_array[$i]["groupname"];
}
function array_get_keys(&$array, $key) {
foreach($array as &$value) $value = $value[$key];
}
array_get_keys($array, 'groupname');
or
function array_get_keys(&$array, $key) {
$result = Array();
foreach($array as &$value) $result[] = $value[$key];
return $result;
}
$new_array = array_get_keys($array, 'groupname');
I'm fairly sure I'm missing something blindingly obvious here but here it goes.
I am working on updating a search function in an application which was running a loop and doing a very large number of sql queries to get object / table relations to one large query that returns everything. However the only way I could think to return relations was period separated, what I am now wanting to do is take the flat array of keys and values and convert it into an associative array to then be jsonified with json_encode.
For example what I have is this...
array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus.Status"=>"Active",
"addressID"=>134,
"address.postcode"=>"XXX XXXX",
"address.street"=>"Some Street"
);
And what I want to turn it into is this...
array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus"=>array(
"Status"=>"Active"
),
"addressID"=>134,
"address"=>array(
"postcode"=>"XXX XXXX",
"street"=>"Some Street"
)
);
Now I'm sure this should be a fairly simple recursive loop but for the life of me this morning I can't figure it out.
Any help is greatly appreciated.
Regards
Graham.
Your function was part way there mike, though it had the problem that the top level value kept getting reset on each pass of the array so only the last period separated property made it in.
Please see updated version.
function parse_array($src) {
$dst = array();
foreach($src as $key => $val) {
$parts = explode(".", $key);
if(count($parts) > 1) {
$index = &$dst;
$i = 0;
$count = count($parts)-1;
foreach(array_slice($parts,0) as $part) {
if($i == $count) {
$index[$part] = $val;
} else {
if(!isset($index[$part])){
$index[$part] = array();
}
}
$index = &$index[$part];
$i++;
}
} else {
$dst[$parts[0]] = $val;
}
}
return $dst;
}
I am sure there is something more elegant, but quick and dirty:
$arr = array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus.Status"=>"Active",
"addressID"=>134,
"address.postcode"=>"XXX XXXX",
"address.street"=>"Some Street"
);
$narr = array();
foreach($arr as $key=>$val)
{
if (preg_match("~\.~", $key))
{
$parts = split("\.", $key);
$narr [$parts[0]][$parts[1]] = $val;
}
else $narr [$key] = $val;
}
$arr = array(
"ID" => 10,
"CompanyName" => "Some Company",
"CompanyStatusID" => 2,
"CompanyStatus.Status" => "Active",
"addressID" => 134,
"address.postcode" => "XXX XXXX",
"address.street" => "Some Street",
"1.2.3.4.5" => "Some nested value"
);
function parse_array ($src) {
$dst = array();
foreach($src as $key => $val) {
$parts = explode(".", $key);
$dst[$parts[0]] = $val;
if(count($parts) > 1) {
$index = &$dst[$parts[0]];
foreach(array_slice($parts, 1) as $part) {
$index = array($part => $val);
$index = &$index[$part];
}
}
}
return $dst;
}
print_r(parse_array($arr));
Outputs:
Array
(
[ID] => 10
[CompanyName] => Some Company
[CompanyStatusID] => 2
[CompanyStatus] => Array
(
[Status] => Active
)
[addressID] => 134
[address] => Array
(
[street] => Some Street
)
[1] => Array
(
[2] => Array
(
[3] => Array
(
[4] => Array
(
[5] => Some nested value
)
)
)
)
)