I am trying to get a new array with all the codes that I get from an array called $houses. I loop thru it. To get the codes I tried $house['code'] This works in the dd but not in the $code = $house['code'].
I would like to know why and what the solution to this is.
$houses = $project['data']['houses'];
$codes = [];
foreach($houses as $house) {
$code = array_column($house, 'code');
//dd($house['code']); //Returns the code "AB12-CD34-EF56-GH78"
if(!$code) {
continue;
} else {
array_push($codes, $code);
}
}
dd($codes); //Returns []
EDIT:
var_dump $houses:
array:60 [
0 => array:30 [
"id" =>
"city" => ""
"code" => "AB12-CD34-EF56-GH78"
"streetName" => ""
"houseNumber" => ""
//And some other stuff that is not relevant to the question
]
]
array_column is for recovering a column from an array inside an array of arrays. $house is a simple array and doesn't contain arrays in it. just use $house['code']
$houses = $project['data']['houses'];
$codes = [];
foreach($houses as $house) {
if(isset($house['code']) && $house['code']) {
$codes[] = $house['code'];
}
}
dd($codes); //Returns ["AB12-CD34-EF56-GH78","AB12-CD34-EF56-GH79", ....]
Instead of this loop, you can simply extract all codes from subarrays with:
$houses = $project['data']['houses'];
$codes = array_column($houses, 'code');
dd($codes);
Related
I have an array that looks like this.
$array = [
0 => 'abc',
1 => [
0 => 'def',
1 => 'ghi'
],
'assoc1' => [
'nassoc' => 'jkl',
'nassoc2' => 'mno',
'nassoc3' => '',
'nassoc4' => false
]
];
The $array can have numeric keys or be an assoc array or a mixed one. The level of nesting is not known. Also the values of the array can also be bool or null or an empty string ''
I need to able to convert this into a scalar array with key value pairs. And then later reconvert it back to the exact same array.
So the scalar array could look like
$arrayScalar = [
'0' => 'abc',
'1[0]' => 'def',
'1[1]' => 'ghi',
'assoc1[nassoc]' => 'jkl',
'assoc1[nassoc2]' => 'mno',
'assoc1[nassoc3]' => '',
'assoc1[nassoc4]' => false
];
And then later be able to get back to the initial $array.
I wrote a parser and it does not currently handle bool values correctly.
I have a feeling this is at best a super hacky method to do what I am after. Also I have been able to test it only so much.
function flattenNestedArraysRecursively($nestedArray, $parent = '', &$flattened = [])
{
$keys = array_keys($nestedArray);
if (empty($keys)) {
$flattened[$parent] = 'emptyarray';
} else {
foreach ($keys as $value) {
if (is_array($nestedArray[$value])) {
$reqParent = (!empty($parent)) ? $parent . '|!|' . $value : $value;
$this->flattenNestedArraysRecursively($nestedArray[$value], $reqParent, $flattened);
} else {
$reqKey = (!empty($parent)) ? $parent . '|!|' . $value : $value;
$flattened[$reqKey] = $nestedArray[$value];
}
}
}
return $flattened;
}
function reCreateFlattenedArray($flatArray): array
{
$arr = [];
foreach ($flatArray as $key => $value) {
$keys = explode('|!|', $key);
$arr = $this->reCreateArrayRecursiveWorker($keys, $value, $arr);
}
return $arr;
}
function reCreateArrayRecursiveWorker($keys, $value, $existingArr)
{
//Outside to Inside
$keyCur = array_shift($keys);
//Check if keyCur Exists in the existingArray
if (key_exists($keyCur, $existingArr)) {
// Check if we have reached the deepest level
if (empty($keys)) {
//Return the Key => value mapping
$existingArr[$keyCur] = $value;
return $existingArr;
} else {
// If not then continue to go deeper while appending deeper levels values to current key
$existingArr[$keyCur] = $this->reCreateArrayRecursiveWorker($keys, $value, $existingArr[$keyCur]);
return $existingArr;
}
} else {
// If Key does not exists in current Array
// Check deepest
if (empty($keys)) {
//Return the Key => value mapping
$existingArr[$keyCur] = $value;
return $existingArr;
} else {
// Add the key
$existingArr[$keyCur] = $this->reCreateArrayRecursiveWorker($keys, $value, []);
return $existingArr;
}
}
}
Is there a better more elegant way of doing this, maybe http_build_query or something else I am not aware of.
Sandbox link -> http://sandbox.onlinephpfunctions.com/code/50b3890e5bdc515bc145eda0a1b34c29eefadcca
Flattening:
Your approach towards recursion is correct. I think we can make it more simpler.
We loop over the array. if the value is an array in itself, we recursively make a call to this new child subarray.
This way, we visit each key and each value. Now, we are only left to manage the keys to assign them when adding to our final resultant array, say $arrayScalar.
For this, we make a new function parameter which takes the parent key into account when assigning. That's it.
Snippet:
$arrayScalar = [];
function flatten($array,&$arrayScalar,$parent_key){
foreach($array as $key => $value){
$curr_key = empty($parent_key) ? $key : $parent_key . '[' . $key . ']';
if(is_array($value)){
flatten($value,$arrayScalar,$curr_key);
}else{
$arrayScalar[$curr_key] = $value;
}
}
}
flatten($array,$arrayScalar,'');
var_export($arrayScalar);
Demo: http://sandbox.onlinephpfunctions.com/code/1e3092e9e163330f43d495cc9d4acb672289a987
Unflattening:
This one is a little tricky.
You might have already noticed that the keys in the flattened array are of the form key1[key2][key3][key4] etc.
So, we collect all these individually in a new array, say $split_key. It might look like this.
array (
'key1',
'key2',
'key3',
'key4',
)
To achieve the above, we do a basic string parsing and added in-between keys to the array whenever we reach the end of the key string or [ or ].
Next, to add them to our final resultant array, we loop over the collected keys and check if they are set in our final array. If not so, set them. We now pass child array reference to our temporary variable $temp. This is to edit the same copy of the array. In the end, we return the result.
Snippet:
<?php
function unflatten($arrayScalar){
$result = [];
foreach($arrayScalar as $key => $value){
if(is_int($key)) $key = strval($key);
$split_key = [];
$key_len = strlen($key);
$curr = '';
// collect them as individual keys
for($i = 0; $i < $key_len; ++$i){
if($key[ $i ] == '[' || $key[ $i ] == ']'){
if(strlen($curr) === 0) continue;
$split_key[] = $curr;
$curr = '';
}else{
$curr .= $key[ $i ];
}
if($i === $key_len - 1 && strlen($curr) > 0){
$split_key[] = $curr;
}
}
// collecting them ends
//add them to our resultant array.
$temp = &$result;
foreach($split_key as $sk){
if(!isset($temp[ $sk ])){
$temp[ $sk ] = [];
}
$temp = &$temp[$sk];
}
$temp = $value;
}
return $result;
}
var_export(unflatten($arrayScalar));
Demo: http://sandbox.onlinephpfunctions.com/code/66136a699c3c5285eed3d3350ed4faa5bbce4b76
I would like to get check my array of the object have title and id. I want to get all the array of objects where id exists in the existing array.
I tried using array_diff or array_intersect but error stating that it is supposed to be an array.
if (!empty(session('selected_movies'))) {
$current_movies = array_intersect($allMovies, session('selected_movies'));
}
The array of objects data
[
{
"id":"05595dd2-2f13-11ea-9e3f-42010a940008",
"title":"Harry Potter"
},
{
"id":"247d20cd-2f13-11ea-9e3f-42010a940008",
"title":"Tom and Jerry"
}
]
Existing array data
["247d20cd-2f13-11ea-9e3f-42010a940008", "51141418-4fb1-11ea-a428-7a79190f5c7d"]
You could do a simple foreach and just unset if its missing desired id
<?php
//Enter your code here, enjoy!
$array = json_decode('[
{
"id":"05595dd2-2f13-11ea-9e3f-42010a940008",
"title":"Harry Potter"
},
{
"id":"247d20cd-2f13-11ea-9e3f-42010a940008",
"title":"Tom and Jerry"
}
]');
$check = ["247d20cd-2f13-11ea-9e3f-42010a940008", "51141418-4fb1-11ea-a428-7a79190f5c7d"];
foreach($array as $index => $current){
if(!in_array($current->id,$check)) unset($array[$index]);
}
print_r($array);
alternativly if you want to create a new array
$mah = [];
foreach($array as $index => $current){
if(in_array($current->id,$check)) array_push($mah,$current);
}
print_r($mah);
I am writing a method which takes an array of $topicNames and an array of $app and concatenates each $app to $topicNames like the following
public function getNotificationTopicByAppNames(array $topicNames, array $apps)
{
$topics = [];
foreach ($topicNames as $topicName) {
foreach ($apps as $app) {
$topic = $app . '_' . $topicName;
$topics[] = $topic;
}
}
return $topics;
}
}
The input and result are like the following...
$topicNames = [
'one_noti',
'two_noti',
'three_noti'
];
$apps = [
'one_app',
'two_app'
];
// The return result of the method will be like the following
[
'one_app_one_noti',
'two_app_one_noti',
'one_app_two_noti',
'two_app_two_noti',
'one_app_three_noti',
'two_app_three_noti'
]
My question is instead of doing nested loops, is there any other way I can do? Why do I want to avoid nested loops? Because currently, I have $topic. Later, I might want to add languages, locations etc...
I know I can use map, reduce, array_walks, each those are basically going through one by one. Instead of that which another alternative way I can use? I am okay changing different data types instead of the array as well.
If you dont care about the order you can use this
function getNotificationTopicByAppNames(array $topicNames, array $apps)
{
$topics = [];
foreach($apps as $app){
$topics = array_merge($topics, preg_filter('/^/', $app.'_', $topicNames));
}
return $topics;
}
print_r(getNotificationTopicByAppNames($topicNames,$apps));
Output
Array
(
[0] => one_app_one_noti
[1] => one_app_two_noti
[2] => one_app_three_noti
[3] => two_app_one_noti
[4] => two_app_two_noti
[5] => two_app_three_noti
)
Sandbox
You can also switch loops and use the $ instead to postfix instead of prefix. Which turns out to be in the same order you had. I thought of prefixing as a way to remove the loop. Then i thought why not flip it.
function getNotificationTopicByAppNames(array $topicNames, array $apps)
{
$topics = [];
foreach($topicNames as $topic){
$topics = array_merge($topics, preg_filter('/$/', '_'.$topic, $apps));
}
return $topics;
}
print_r(getNotificationTopicByAppNames($topicNames,$apps));
Output
Array
(
[0] => one_app_one_noti
[1] => two_app_one_noti
[2] => one_app_two_noti
[3] => two_app_two_noti
[4] => one_app_three_noti
[5] => two_app_three_noti
)
Sandbox
The trick here is using preg_filter.
http://php.net/manual/en/function.preg-filter.php
preg_filter — Perform a regular expression search and replace
So we search with ^ start or $ end which doesn't capture anything to replace and then we just add on what we want. I've used this before when I wanted to prefix a whole array with something, etc.
I couldn't test it in a class, so I made it a regular function, so adjust as needed.
Cheers!
You can use :
<?php
public function mergeStacks(...$stacks)
{
$allStacks = call_user_func_array('array_merge', $stacks);
return $this->concatString($allStacks);
}
private function concatString(&$stack, $index = 0, &$result = [])
{
if(count($stack) == 0){
return '';
}
if($index == count($stack)){
return $result;
}
array_walk($stack, function($value, $key) use($index, &$result, $stack){
if($key > $index){
array_push($result, $stack[$index] . '_' . $value);
}
});
$index = $index + 1;
return $this->concatString($stack, $index, $result);
}
And then when you want to get the array, no matter if you have languages or topics etc, you can just do :
$this->mergeStacks($languages, $topics, $locations, .....);
Where $languages, $topics, $locations are simple arrays.
Instead of accepting only topics name parameter try something like this:
function getNotificationTopicByAppNames(array $apps, array ...$names)
{
$topics = [];
foreach ($names as $nameArray) {
foreach ($nameArray as $topicName) {
foreach ($apps as $app) {
$topic = $app . '_' . $topicName;
$topics[] = $topic;
}
}
}
return $topics;
}
$topicNames = [
'one_noti',
'two_noti',
'three_noti'
];
$languagesNames = [
'test_en',
'test_other',
'test_other2'
];
$apps = [
'one_app',
'two_app'
];
print_r(getNotificationTopicByAppNames($apps,$topicNames,$languagesNames));
you can pass any number of arrays to array.
This question already has answers here:
PHP array replace after matching value [duplicate]
(2 answers)
Closed 2 months ago.
Am using Php as my serverside scripting language.In my project I used Json string decoded into array.
My problem is how to overwrite the existing array index based on an array value.
my existing array looks like :
$array1 =[
{
"Name":"apple",
"color":"red",
"property":[
{
"p1":"value1",
"p2":"value2"
}
]
},
{
"Name":"Grape",
"color":"violet",
"property":[
{
"p1":"value1",
"p2":"value2"
}
]
}
];
and the updated array content looks:
$upadatearray = [
{
"Name":"apple",
"color":"green",
"property":[
{
"p1":"newvalue",
"p2":"newvalue2"
}
]
}
];
I want to update the existing $array1 with new $upadatearray , bsed on the "Name" .If it is same then replace.
I want to look like:
$finalarray =[
{
"Name":"apple",
"color":"green",
"property":[
{
"p1":"newvalue",
"p2":"newvalue2"
}
]
},
{
"Name":"Grape",
"color":"violet",
"property":
[
{
"p1":"value1",
"p2":"value2"
}
]
}
];
I tried this :
for($j=0;$j<count($array1);$j++)
{
if($array1[$j]['Name'] == $upadatearray[0]['Name'])
$finalarray = array_replace($array1[$j],$upadatearray[0]);
}
But it will not work correctly.Is there any possible solution ?
Let you have this two arrays:
$array1 ='[{"Name":"apple","color":"red","property":[{"p1":"value1","p2":"value2"}]},{"Name":"Grape","color":"violet","property":[{"p1":"value1","p2":"value2"}]}]';
$upadatearray = '[{"Name":"apple", "color":"green", "property":[{"p1":"newvalue","p2":"newvalue2"}]}]';
$array1 = json_decode($array1, true);
$upadatearray = json_decode($upadatearray, true);
You can use array_replace function. But to make it replace items based on the Name column you should first make this column a key of array
function make_column_key($arr, $col_name) {
$keys = array_column($arr, $col_name);
$result = array_combine($keys, $arr);
return $result;
}
$array1 = make_column_key($array1, 'Name');
$upadatearray = make_column_key($upadatearray, 'Name');
And now simply use array_replace
$finalarray = array_replace($array1, $upadatearray);
If you don't need Name be the key of final array, you can get only values:
$finalarray = array_values($finalarray);
hi I think this code will help you.
//what i did is i created a final array variable which gets the value of old array.
$finalArray = $array1;
//then i perform a foreach loop for old array
foreach ($array1 as $key => $oldarray) {
//inside the updated array
foreach ($upadatearray as $key => $newarray) {
//if old array name and new array name is same replace content on the final array
if ($oldarray['Name'] == $newarray['Name']) {
$finalArray['Name'] = $newarray['Name'];
}
}
}
I have a database with project entries. Each entry has a project title, datestamp, the user who entered it, and a comment. I am trying to format this data as JSON for reporting and charts.
I want an array for each project name, and inside that array an array for each entry.
I've tried several approaches but I haven't had much luck yet.
if ($result = $mysqli->query("SELECT * FROM project_entries"))
// WHERE WEEK(date) = WEEK(current_date) ORDER BY project_name
{
while ($row = mysqli_fetch_array($result)) {
$entry_array = array();
$row_array['project_name'] = $row['project_name'];
$comment = $row['comment'];
$entry = array (
'comment' => $comment,
);
$row_array['entries'] = $entry;
if ( !in_array($row['project_name'], $projects, false ))
{
array_push($projects, $row_array);
}
}
}
Outputs:
[
{
"project_name": "Logo Design",
"entries": {
"comment": "Worked on a thing"
}
},
{
"project_name": "Logo Design",
"entries": {
"comment": "Created some stuff"
}
},
While I want:
{
"project_name": "Logo Design",
"entries": {
"comment": "Worked on a thing",
"comment": "Created some stuff"
}
}
This should do the trick. You can use the project name as an array key. In order to prevent the string keys from showing up in your output array, you can use array_values to convert them to numeric keys.
$projects = array();
while ($row = mysqli_fetch_array($result)) {
$projects[$row['project_name']]['project_name'] = $row['project_name'];
$projects[$row['project_name']]['entries'][] = array('comment' => $row['comment']);
}
echo json_encode(array_values($projects));
What was going wrong with your previous code:
if ($result = $mysqli->query("SELECT * FROM project_entries")) {
while ($row = mysqli_fetch_array($result)) {
$entry_array = array(); // This does not appear to be used
// With each iteration of the while loop, you create a new array of
// project information (project name and entries array with one comment)
$row_array['project_name'] = $row['project_name'];
$comment = $row['comment'];
$entry = array ('comment' => $comment);
$row_array['entries'] = $entry;
// The $projects array is an array of arrays, but $row['project_name'] is
// a string. Checking if this string is in an array of arrays will always
// be false, so the array_push should always execute.
if (!in_array($row['project_name'], $projects, false )) {
// Adds the new project array to the projects array
array_push($projects, $row_array);
}
// This is not producing what you want because you are adding a new
// array to $row_array each time the loop runs
}
}
Why the code I suggested works:
$projects = array(); // Empty array to hold all the projects
while ($row = mysqli_fetch_array($result)) {
// Using the project name from the database as an array key in the array we are
// constructing keeps the projects unique in that array.
// The first time a new project name occurs, this will create a new sub-array
// within $projects with project_name => the new project name. This value will
// be overwritten on subsequent occurrences of the same project name.
$projects[$row['project_name']]['project_name'] = $row['project_name'];
// For each iteration, this will add a comment to the 'entries' array in the
// project array with the key $row['project_name'].
$projects[$row['project_name']]['entries'][] = array('comment' => $row['comment']);
// For example, with the first iteration of the array we create the following:
//
// $projects['Logo Design'][
// 'project_name' =>'Logo Design',
// 'entries' => [0 => ['comment' => 'Worked on a thing'] ] ]
//
// with the second iteration, the project name is overwritten (with same project name)
// and another comment array is added to the entries array
//
// $projects['Logo Design'][
// 'project_name' =>'Logo Design',
// 'entries' => [0 => ['comment' => 'Worked on a thing'],
// 1 => ['comment' => 'Created some stuff'] ] ]
}
// If you just did echo json_encode($projects), you would not get the format you want,
// because of the string keys. Try it without the array_values() to see what I mean.
echo json_encode(array_values($projects));
Maybe something like that?
Use project id to build target array.
while ($row = mysqli_fetch_array($result) {
if (!isset($projects[$row['id']]))
{
$projects[$row['id']] = [
'project_name' => $row['project_name'],
'entries' => [],
];
}
$projects[$row['id']]['entries'][] = [
'comment' => $row['comment'],
];
}