Counting Items Inside Multidimensional Associative Array - php

So I have the following array of data in PHP
$array = array(
"animal" => "panda",
"location" => "San Diego",
"age" => "2",
),
array(
"animal" => "tiger",
"location" => "Bronx",
"age" => "5",
),
array(
"animal" => "panda",
"location" => "Bronx",
"age" => "3",
),
array(
"animal" => "tiger",
"location" => "bronx",
"age" => "3",
),
array(
"animal" => "panda",
"location" => "San Diego",
"age" => "2",
)
)
What I want to do is convert this into an associative array that will contain the count for the animals, locations and age. so if I wanted to see how many pandas are in san diego and are age 2 I would access the new array with $newArray['panda']['San Diego']['2'] and the output would be 2.
My issue is I can easily run a loop and build an array and count the items when it is completely static like so.
foreach($array as $a) {
$newArray[$a['animal']][$a['location']][$a['age']] += 1;
}
However I want to know how to accomplish the same concept when the number of keys is dynamic. for instance what if there are only location and animal in one call and sometimes there might be location, animal, age, and gender in another call.
There are some examples I have found that expound on doing this for associative arrays but not for multidimensional arrays with this particular use case.
Any Thoughts?

The Idea
It looks to me as if you're trying to do too much in one go. Instead of transforming your array to contain all your answers, consider making a function to run queries against it.
The Solution
/**
* #param array $animals The whole animals array
* #param array $query Array containing keys and values you want to filter by
*
* #return array Animals that match $query
*/
function filterAnimals($animals, $query) {
return array_filter($animals, function ($animal) use ($query) {
// Check if $animal has every key and the corresponding value from $query
foreach ($query as $key => $value) {
if (!isset($animal[$key]) || $animal[$key] != $value) {
return false;
}
}
return true;
});
}
filterAnimals() filters your $animals array and returns only the animals that have the common keys and values with the $query array. Searching for all pandas from San Diego would look like this:
$result = filterAnimals($animals, [
'animal' => 'panda',
'location' => 'San Diego'
]);
Then, if you wish, you can count the $result:
$count = count($result);

Related

Extracting associated value of nested array using unique value in PHP

I am aware that I could use a loop to answer my question, but I was hoping that maybe PHP has a function to do what I am trying to achieve and that someone might know.
Basically I am trying to identify a unique key from a series of arrays and then extract the value of the correlated key in the array.
So basically, from this array:
$myarray = array(array("id" => 1, "label" => "True"), array("id" => 2, "label" => "False"))
I want to be able to find the label value when the id is searched and matched, i.e. $id = 1 should return True.
Any simple functions available to do this without having to write a couple of loops?
It would be one simple loop. But if you are loopofobic, then you can rely on other functions (that acts as loop too):
function find(array $inputs, int $search): ?string
{
$result = array_filter($inputs, fn ($input) => $input['id'] === $search);
return current($result)['label'] ?? null;
}
$myarray = [["id" => 1, "label" => "True"], ["id" => 2, "label" => "False"]];
var_dump(find($myarray, 1)); // string(4) "True"
var_dump(find($myarray, 2)); // string(5) "False"
var_dump(find($myarray, 3)); // NULL
Live Example
you may use the built-in function array_column() for your aim.
$myarray = array(array("id" => 1, "label" => "True"), array("id" => 2, "label" => "False"));
/* label (value) per id (key) in 1-dimensional array.*/
print_r(array_column($myarray,'label','id'));
will return
Array
(
[1] => True
[2] => False
)
so you may adjust the code below.
$myarray = array(array("id" => 1, "label" => "True"), array("id" => 2, "label" => "False"));
$id_val = 1;
$output = isset(array_column($myarray,'label','id')[$id_val]) ? array_column($myarray,'label','id')[$id_val] : 'key not found';
var_dump($output);

Foreach array return last value

I'm learning OOP and I whould create a list of objects in an array, but my code return the last array
I have search here, but haven't found a solution or idea how to do this.
Excepct
"MerchantDefinedFields":[
{
"Id":2,
"Value":"email#test.com"
},
{
"Id":4,
"Value":"Web"
},
{
"Id":9,
"Value":"NAO"
},
{
"Id":83,
"Value":"Field"
},
{
"Id":84,
"Value":"Only"
}
]
My code
$MDDs = array(
array("Id" => 2, "Value" => "email#test.com"),
array("Id" => 4, "Value" => "Web"),
array("Id" => 9, "Value" => "NO"),
array("Id" => 83, "Value" => "Field"),
array("Id" => 84, "Value" => "Only")
);
foreach($MDDs as $MDD){
$abac = array("Id" => $MDD['Id'], "Value" => $MDD['Value']);
}
Result
Array
(
[Id] => 84
[Value] => PROPRIO
)
Your foreach() is re-setting $abac every time it goes through the loop. So on the last time it runs, it will set the variable to the last item in your array.
Instead of setting the variable each time, try adding the key->value to an array (or something like that, depending on what you want):
$abac = [];
foreach($MDDs as $MDD){
$abac[] = array("Id" => $MDD['Id'], "Value" => $MDD['Value']);
}
It's hard to create the exact right answer for you, since it's unclear what you're trying to accomplish, but this should at least point you in the right direction.
For simple answer :- You don't need foreach loop to get the desired result
you can simply use built-in php function to convert your array to JSON
$abac = json_encode ( $MDDs);
Now coming to your problem :-
you are re-assigning the $abac variable in loop instead of adding values to it like .
$abac = [];
foreach($MDDs as $MDD){
$abac[] = array("Id" => $MDD['Id'], "Value" => $MDD['Value']);
}
The best way to do it is to declare the $abac outside of the foreach and then use the array_push method like this:
$abac = array();
foreach($MDDs as $MDD)
{
array_push($abac, array("Id" => $MDD['Id'], "Value" => $MDD['Value']));
}
print_r($abac);

Regex Preg_match Pattern for Numbers In Array PHP

I have an array of numbers that I need to search through a multidimensional array for.
I have a thousand records of songs. Each song has an array of float values that I need to search through, and I'll need to retrieve the songs if the first digits of each float value match any float number in my array.
So for example my array of numbers I need to find are:
array(14, 18.12, 12.1290, 55.01)
and the songs are sorted in a json file like so:
{"id": 129112, "name": "XYZ Song", "values": { 14.1290, 55.0192, 129 } }
Currently my for loops are taking too long to loop through all the records.
I think I need to sort through the values with a preg_match function and the right pattern (except I'm terrible with regex), what do you guys think?
Please check this code. This code may help you
<?php
// PHP program to carry out multidimensional array search
// Function to recursively search for a given value
function multi_array_search($search_value, $array, $id_path) {
if(is_array($array) && count($array) > 0) {
foreach($array as $key => $value) {
$temp_path = $id_path;
// Adding current key to search path
$temp_path[] = $value;
// Check if this value is an array
// with atleast one element
if(is_array($value) && count($value) > 0) {
$res_path = multi_array_search(
$search_value, $value, $temp_path);
}
else if($value == $search_value) {
print_r($temp_path);
}
}
}
}
// Multidimensional (Three dimensional) array as suggested by you
$songs_array= array(
0 => array(
"id" => "129112",
"name" => "X Song",
"value" => array( 14.1290, 329, 129 )
),
1 => array(
"id" => "129113",
"name" => "XY Song",
"value" => array( 14.1291, 55.0192, 229 )
),
2 => array(
"ic" => "129114",
"name" => "XYZ Song",
"value" => array( 14.1292, 55.0193, 388 )
)
);
$songs= multi_array_search('329', $songs_array, array());
?>
Here I have searched for 329 in $song_array and
Result is :

php replace ids in array

I got the following array:
"task" : {
"author_id" : 150,
"created_at" : somedate,
"status_id" : 2,
"assignee_id" : 100,
"updated_at" : somedate_too
and I got 2 more associative arrays where I store names for IDs in the following way:
"100" => Mike,
"150" => Bob //etc..., the same for statuses
I need to check for the IDs in the first array and replace numbers with names for the corresponding arrays in the most effective way. I tried the following:
if(isset(task['status_id'])){$row = array_merge($row, [$status_ids[
task['status_id']]]);}else{$row = array_merge($row, '');}
if(isset(task['author_id'])){row = array_merge($row, [$users[// note the different array here
task['author_id']]]);}else{$row = array_merge($row, '');}
if(isset(task['assignee_id'])){$row = array_merge($row, [$users[
task['assignee_id']]]);}else{$row = array_merge($row, '');}
In my resulting array ($row) I cannot miss the index and replace it with another value. If there is no value in the first array, I need to insert an empty string to get the following, for example:
['in progress', '', 'Mike']
if there is no author_id in the first array. I believe there should be a better way to do it with foreach loop, but I cant find out how because for different fields I get the data from different arrays. I dont think a separate if clause for every field is the most suitable here.
Any help would be welcome. Thank You.
You could map your special keys to their array counterparts using references and use that mapping when populating $row, like this:
$users = [
"100" => "Mike",
"150" => "Bob",
];
$status_ids = [
1 => "Foo",
2 => "Bar",
];
// Define output format and array mapping
$mapping = [
"author_id" => &$users, // Mapped to $users array
"created_at" => null, // Not mapped, keep $task value
"status_id" => &$status_ids,
"assignee_id" => &$users,
"updated_at" => null,
];
$task = [
"author_id" => 150,
"created_at" => "Some date",
"status_id" => 2,
// "assignee_id" => 99999, // Oops, missing key/value => empty string in $row
"updated_at" => "Some other date",
];
foreach ($mapping as $key => $mappedArray) {
#$row[] = $mappedArray
? $mappedArray[$task[$key]] ?: ''
: $task[$key];
}
print_r($row);
Output:
Array
(
[0] => Bob
[1] => Some date
[2] => Bar
[3] =>
[4] => Some other date
)
It should work (I didn't try it, but it should give you the general idea):
<?php
$fields = array("author_id", "assignee_id", "status_id");
$aliases = array("users", "users", "status_ids");
foreach ($task as $key=>&$value) {
$alias = str_replace($fields, $aliases, ${$key});
if (is_array(${$alias}) {
$value = array_key_exists($value, ${$alias}) ? ${$alias}[$value] : "";
}
}
unset($value);
And then you can fill up your $row as you planned, directly from the $task array.

Building an array of search parameters

I need some help wrapping my head around a problem. I have an array filled with other arrays. I need to:
Loop through the entire array and build a new array called finalOptions
Each iteration of the loop will take a new SearchIndex and apply the other paramenters
i.e
SearchIndex => SportingGoods
MinPercentageOff => 50
MinimumPrice => 1
ItemPage => 1
Sort => salesrank
BrowseNode => 2342470011
THEN:
Final array should contain data like this
SearchIndex => SportingGoods
MinPercentageOff => 60
MinimumPrice => 100
ItemPage => 2
Sort => salesrank
BrowseNode => 3403201
Basically, I'm creating a new array and sending it to another method that will execute a call to an API and return a result, then doing it again until my array options are complete.
This might not be the way to go and I'm looking for suggestions/pseudo code on an approach. Here is the basics of what I have so far:
Starting with this code
$allOptions = array(
"SearchIndex" => array("SportingGoods", "Tools"),
"MinPercentageOff" => array("50", "60", "70"),
"MinimumPrice" => array("1", "100", "1000"),
"ItemPage" => array("1", "2"),
"Sort" => array("salesrank")
"BrowseNode" => array(
"SportingGoods" => array("2342470011", "3403201"),
"Tools" => array("511364")
)
)
$finalOptions = array();
foreach($allOptions as $options){
foreach($options["SearchIndex"] as $searchIndex){
$finalOptions[] = "SearchIndex" => $searchIndex[]
}
$this->itemSearch($finalOptions);
}
EDIT
The arrays will contain more values. i.e "ItemPage" => array("1", "2"), will have 1 - 10. The others will have more values as well.
From the given array it will produce 54 possible combinations as you described.
Also you need to make sure you have array in $allOptions['BrowseNode'] indexed as each value of $allOptions['SearchIndex']. Otherwise it will produce error.
Cartesian function from here.
$allOptions = [
"SearchIndex" => ["SportingGoods", "Tools"],
"MinPercentageOff" => ["50", "60", "70"],
"MinimumPrice" => ["1", "100", "1000"],
"ItemPage" => ["1", "2"],
"Sort" => ["salesrank"],
"BrowseNode" => ["SportingGoods" => ["2342470011", "3403201"], "Tools" => ["511364"] ] ];
$finalOptions = $allOptions; // copy our initial $allOptions array
unset($finalOptions['BrowseNode']); // deal with BrowseNode key later with custom iterator
$cartesian_product = cartesian($finalOptions); // find cartesian except BrowseNode
foreach($cartesian_product as $cartesian) // each member of cartesian product will iterate here
{
foreach($allOptions['BrowseNode'][$cartesian['SearchIndex']] as $possible)
/*
We have unset the BrowseNode, so need to refer original $allOptions array for BrowseNode,
In every cartesian product, we will get $cartesian['SearchIndex'] and it will contain either
'SportingGoods' or 'Tools' , so in our original array, look for 'BrowseNode' value, having key
same as $cartesian['SearchIndex'].
$allOptions['BrowseNode'][$cartesian['SearchIndex']] <---- is similar to below two lines
$key = $cartesian['SearchIndex'];
$allOptions['BrowseNode'][$key];
Finally iterate through $allOptions['BrowseNode'][$cartesian['SearchIndex']] will iterate as many times,
as many values there are
*/
{
$cartesian['BrowseNode'] = $possible; // assign the long waited key here to 'BrowseNode'
var_dump($cartesian); // here you can do $this->itemSearch($cartesian);
}
}
function cartesian($input) {
$input = array_filter($input);
/*
will renove any false values in input array,
in our array's case, it will do nothing.
*/
$result = [[]];
foreach ($input as $key => $values) {
$append = [];
foreach($result as $product) {
foreach($values as $item) {
$product [$key] = $item;
$append [] = $product;
}
}
$result = $append;
}
return $result;
}

Categories