PHP How can I pass values from one array to another? - php

I'm trying to pass some of the values from theOptions array and drop them into a new array called $theDefaults.
$theOptions = array(
'item1' => array('title'=>'Title 1','attribute'=>'Attribute 1','thing'=>'Thing 1'),
'item2' => array('title'=>'Title 2','attribute'=>'Attribute 2','thing'=>'Thing 2'),
'item3' => array('title'=>'Title 3','attribute'=>'Attribute 3','thing'=>'Thing 3')
);
So, $theDefaults array should look like this:
$theDefaults = array(
'Title 1' => 'Attribute 1',
'Title 2' => 'Attribute 2',
'Title 3' => 'Attribute 3'
);
However, I cannot figure out how to do this.
Have tried this but it is clearly not quite working.
$theDefaults = array();
foreach($theOptions as $k=>$v) {
array_push($theDefaults, $v['title'], $v['attribute']);
}
but when I run this...
foreach($theDefaults as $k=>$v) {
echo $k .' :'.$v;
}
It returns this.
0 :Title 11 :Attribute 12 :Title 23 :Attribute 24 :Title 35 :Attribute 3
Looks to be soooo close, but why are the numbers in the array?

It's even simpler than that:
$theDefaults = array();
foreach($theOptions as $v) {
$theDefaults[$v['title']] = $v['attribute'];
}

Related

Grabbing information between 2 dates in php

I have an array that looks something like this
$data =
[
[
'date' => '2020-10-01',
'product' => 'Product 1',
'description' => 'Product 1',
],
[
'date' => '2020-11-01',
'product' => 'Product 2',
'description' => 'Product 2',
],
[
'date' => '2020-12-01',
'product' => 'Product 3',
'description' => 'Product 3',
],
[
'date' => '2021-01-01',
'product' => 'Product 4',
'description' => 'Product 4',
]
];
And what I would like to do is grab all the information between 2 dates.
For example I want everything between 2021-01-01 and 2020-11-01 and it would then display Product 2, Product 3 and Product 4
I'm not sure how to go about this
<?php
$data =
[
[
'date' => '2020-10-01',
'product' => 'Product 1',
'description' => 'Product 1',
],
[
'date' => '2020-11-01',
'product' => 'Product 2',
'description' => 'Product 2',
],
[
'date' => '2020-12-01',
'product' => 'Product 3',
'description' => 'Product 3',
],
[
'date' => '2021-01-01',
'product' => 'Product 4',
'description' => 'Product 4',
]
];
$from = new DateTime('2020-11-11');
$to = new DateTime('2030-10-13');
foreach ($data as $d){
$productDate = new DateTime($d['date']);
if (($productDate >= $from) && ($productDate <= $to)){
echo "is between";
var_dump($d);
}
}
In case you want to do this in PHP you can create a similar function to SQL's WHERE ... BETWEEN ... AND ... using array_filter.
If you have access to the SQL query then probably you want to have the DBMS take care of this as #RiggsFolly mentioned in the comments.
$lowerBound = strtotime('2020-11-01');
$upperBound = strtotime('2021-01-01');
$result = array_filter($data, function ($item) use ($lowerBound, $upperBound) {
$itemDate = strtotime($item['date']);
return $lowerBound <= $itemDate && $itemDate <= $upperBound;
});
echo '<pre>';
print_r($result);
echo '</pre>';
As per the comments if the data is originally sourced from a database query it's a much better idea to limit the content there, for example:
// SQL query to be used in a prepared statement
SELECT date, product, description
FROM products
WHERE date >= ?
AND date <= ?
However, failing that, the key thing here is that the dates are all properly formatted: timetamps follow the pattern Y-m-d which means that both the chronological and alphabetical order are the same
Generally...
Start ===> End
A ===> Z
1 ===> 10
0000-00-00 ===> 9999-99-99
Which means...
2020-12-30 < 2020-12-31 < 2021-01-01
That being the case when we compare two properly formatted dates (in the same format) we have no need to alter the data type/format; converting the string with DateTime or strtotime adds nothing except ~10x the required time compared to comparing the values in string format.
Anyway, comparing the dates:
Using array_filter
$minDate = '2020-11-01';
$maxDate = '2021-01-01';
$result = array_filter($data, function ($item) use ($minDate, $maxDate) {
return $minDate <= $item["date"] && $item["date"] <= $maxDate;
});
Using foreach
$minDate = '2020-11-01';
$maxDate = '2021-01-01';
$result = [];
foreach($data as $item){
if($minDate <= $item["date"] && $item["date"] <= $maxDate){
$result[] = $item;
}
}

Differentiate between dynamic and manually assigned array keys

I was looking for a way to shorten my code, and could not find the answer to this question.
In this sample array:
$addressData = array(
'Full Name',
'Address Line 1',
'Address Line 2',
30 => 'City/Town',
22 => 'Province/State/Region',
27 => 'Postal/ZIP code',
'Country',
);
The first three values will be assigned keys 0, 1, and 2, respectively. The last value (Country) will be assigned key 31.
When I walk through this array, is there any way that I can treat those manually assigned values in different manner than the automatically assigned values?
I can't find anything in the manual, but I thought the community might be able to help.
Edit for further clarification. This is not real code, but it explains what I hope to achieve:
foreach($addressData as $key => $value){
if(is_set_manually($key)){
$someValue = TRUE;
}
}
Not sure if i understand your question correctly, but if you want to fix sequence if it's broken you can do something like this:
<?php
$addressData = array(
'Full Name',
'Address Line 1',
'Address Line 2',
30 => 'City/Town',
22 => 'Province/State/Region',
27 => 'Postal/ZIP code',
'Country',
);
$result= [];
$first = 0;
foreach($addressData as $key=>$data){
if($key != $first && ($key > $first+1)){
$newkey = $first;
$result[$newkey] = $data;
}else{
$result[$key] = $data;
}
$first++;
}
print_r($result);
And new array $result looks like:
Array
(
[0] => Full Name
[1] => Address Line 1
[2] => Address Line 2
[3] => City/Town
[4] => Province/State/Region
[5] => Postal/ZIP code
[6] => Country
)
If you can assign array like following format may be helpful for your answer.
<?php
$addressData = array(
'Full Name',
'Address Line 1',
'Address Line 2',
array(30 => 'City/Town'),
array(22 => 'Province/State/Region'),
array(27 => 'Postal/ZIP code'),
'Country',
);
foreach($addressData as $key => $value){
if(is_array($value)){
echo 'Manually Key<br>';
} else {
echo 'Dynamic Key<br>';
}
}
?>

2D array loses its format when received as a function return

I can not figure out why this happens.
function modified_my_2d_array() {
my_2d_array = array(
0 => array(
'Unique Identifier' => '1',
'Other Column' => 'Random text',
),
1 => array(
'Unique Identifier' => '10',
'Other Column' => 'Random text',
),
2 => array(
'Unique Identifier' => '300',
'Other Column' => 'Random text',
),
3 => array(
'Unique Identifier' => '30',
'Other Column' => 'Random text',
),
);
foreach ($my_2d_array as &$row) {
if (in_array($row['Unique Identifier'], $unique_identifiers_needed)) {
$row['STO_UID'] = $row['Unique Identifier'];
}
else {
$row['STO_UID'] = str_pad($row['Unique Identifier'], 3, '0', STR_PAD_LEFT);
}
}
// Here the "STO_UID" column is formated as XXX. Ex: 001, 010, 300, 030.
return $my_2d_array;
}
function calling_function() {
$my_array = modified_my_2d_array();
// Here the "STO_UID" column is not formated as XXX anymore. Ex: 1, 10, 300, 30.
}
Im trying to always have the STO_UID in a XXX format but, while that format is being remembered whitin the function where the array is being modified, its format is lost when assigned to a variable as a return array of a function... Any ideas ?

Get keys from multidimentional array by value

I need to get all "top level" keys from multidimensional array by searching the "bottom level" values. Here is an example of the array:
$list = array (
'person1' => array(
'personal_id' => '1',
'short_information' => 'string',
'books_on_hand' => array(
'Book 1',
'Book 2',
'Book 3',
)
),
'person2' => array(
'personal_id' => '2',
'short_information' => 'string',
'books_on_hand' => array(
'Book 4',
'Book 2',
'Book 5',
)
),
'person3' => array(
'personal_id' => '3',
'short_information' => 'string',
'books_on_hand' => array(
'Book 4',
'Book 2',
'Book 1',
'Book 3',
)
),
//etc...
);
I want to know all persons who have "Book 2" on hand. I can get that information by loop like this:
foreach ($list as $person => $info){
$check = array_search( 'Book 2', array_column($info, 'books_on_hand') );
if ( $check !== false ){
$results .= 'Name: '.$person;
$results .= 'ID: '.$info['personal_id'];
//get other infos other stuff, if necessary
}
}
The problem is, that foreach in this case is very heavy on memory and only grows more when array has a thousand+ entries. It needs to run through all of the persons, even if only 3 persons at the very top of the array have "Book 2".
I have been trying to optimize it by getting persons with "Book 2" using built-in functions like array_search, array_keys, array_column and only then run foreach for persons found, but I had no luck with getting "top level" keys.
Is it possible to optimize or use built-in function to search multidimensional array?
One way would be to filter it first. Now your result is structured like $list but it only contains elements with the needed book:
$find = 'Book 2';
$result = array_filter($list, function($v) use($find) {
return in_array($find, $v['books_on_hand']);
});
If all you're interested in is the person key and personal_id then this:
$find = 'Book 2';
$result = array_map(function($v) use($find) {
if(in_array($find, $v['books_on_hand'])) {
return $v['personal_id'];
}
}, $list);
Will return something like this for persons with the needed book:
Array
(
[person1] => 1
[person2] => 2
[person3] => 3
)

Multidimensional Array - Pulling Data

New to PHP and after spending hours researching on here, nothing seems to be exactly what I need. I have a multi dimensional array that I'm looking to pull data and COUNT from. FOR Instance:
array (
'loyola' => NULL,
'gold_coast' => NULL,
'lincolnpark' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3',
3 => 'Building 4'
),
'lakeview' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3'
),
)
I'm looking to essentially create a table that lists all the buildings and in the next column the number of times that building appears.
This what I've gotten thus far, but it only displays all buildings.
$buildings = unserialize($row['buildings']);
$lincolnpark = $buildings['lincolnpark'];
$loyola= $buildings['loyola'];
$gold_coast = $buildings['gold_coast'];
$lakeview = $buildings['lakeview'];
foreach ($lakeview as $value)
{
echo $value;
}
}
Try the code below. It will navigate recursively into the array and will print the qtd each build appear.
<?php
$arr = array (
'loyola' => NULL,
'gold_coast' => NULL,
'lincolnpark' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3',
3 => 'Building 4'
),
'lakeview' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3'
),
);
$ret = array();
countBuildings($arr);
foreach($ret as $key=>$value){
echo "Building: $key ==> qtd : $value <br>";
}
function countBuildings($arr = array()){
global $ret;
foreach($arr as $value){
if(is_array($value)){
countBuildings($value);
}else{
if($value != NULL){
if(isset($ret[$value])){
$ret[$value] += 1;
}else{
$ret[$value] = 1;
}
}
}
}
}
Do it in two passes: one for counting building occurrences in a separate array, and another for output.

Categories