Hey Guys I have a quick question. I have an array that is as follows:
[0]=>
array(2) {
["id"]=>
string(3) "Prod ID"
["qty"]=>
string(1) "2"
}
Now this array has all of the orders from a given group of people. This means that product ID will be listed more then once.
I am trying to combine them and increment the qty so that I can pull a report against the top 5 products sold. But I am not sure how to accomplish this as I am new to arrays.
I tried putting it into a loop and setting it to a second array, then if the product ID matched one in the existing array, it would add the qty values together.
Any help would be much Appreciated.
Normally, what you do here is that you group them to another array and loop them using the id, making it a key. When a key is assigned, it is pushed inside normally, if it already exists, just add the existing quantity to the one on the current loop. Example:
$new_data = array();
foreach($data as $value) {
// simple initialization
if(!isset($new_data[$value['id']])) {
$new_data[$value['id']] = array('id' => $value['id'], 'qty' => 0);
}
// then sum up the quantity
$new_data[$value['id']]['qty'] += $value['qty'];
}
$new_data = array_values($new_data); // simple reindex
Then to get the top 5, sort it to descending first, get slice the array to get the 5.
usort($new_data, function($a, $b){
return $b['qty'] - $a['qty']; // sort descending
});
// get top 5
$top_5 = array_slice($new_data, 0, 5);
Use this:
foreach ($arr as $value)
$newArr[$value['id']] = (isset($newArr[$value['id']])) ? $newArr[$value['id']] + $value['qty'] : $value['qty'] ;
Here an example how you should do it:
$test = [
[
"id" => "1",
"qty" => "2"
],
[
"id" => "1",
"qty" => "2"
],
[
"id" => "2",
"qty" => "2"
],
[
"id" => "4",
"qty" => "1"
],
[
"id" => "2",
"qty" => "3"
],
[
"id" => "4",
"qty" => "1"
]
];
foreach ($test as $value)
$newArr[$value['id']] = (isset($newArr[$value['id']])) ? $newArr[$value['id']] + $value['qty'] : $value['qty'] ;
arsort($newArr);
print_r($newArr);
OUTPUT
Array
(
[2] => 5
[1] => 4
[4] => 2
)
Now you have an id as key and the sum of the qty related to this id as a value. It was sorted with arsort so you can treat the informations easily.
Related
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);
I am parsing a csv file, and then looping it like so.
foreach ($this->csvData as $dataKey => &$item) {
foreach ($item as $key => $value) {
print_r($item);
}
}
Now if I output item, I can see something like the following
array:12 [
"ID" => "12345"
"CODE" => "AZ6G"
"YEAR" => "2009"
"WEEK" => "13"
"FULL_DATE" => "29/04/2014"
"SALES" => "asdas89.34"
"QUANTITY" => "3"
]
So the above example represents one row in the csv, the key is the header name and then it has a value.
The problem is this, I know which columns I need to keep based on an index value. These values are selected by the user at a previous stage. So in the above example I know I need to keep the ID, FULL_DATE and SALES, so in my database I have 0, 4, 5 which represents their indexes.
Now I need to extract these columns. If I do something like the following
foreach ($this->csvData as $dataKey => &$item) {
foreach ($item as $key => $value) {
print_r($item[4]);
}
}
I will get an undefined index problem as there is no key named 4. If I give it the name of the key, it will work, and show me the value.
So how can I get the value using the key index instead of the name?
Thanks
you could use array_keys and then loop over those keys you said you get from the Database like so:
<?php
$keys = [0, 4, 5];
$data = [
"ID" => "12345",
"CODE" => "AZ6G",
"YEAR" => "2009",
"WEEK" => "13",
"FULL_DATE" => "29/04/2014",
"SALES" => "asdas89.34",
"QUANTITY" => "3"
];
foreach($keys as $key) {
echo $data[array_keys($data)[$key]] . "\n";
}
// outputs:
// 12345
// 29/04/2014
// asdas89.34
Explanation what happens:
array_keys($data)[0]; // is "ID"
// and the "ID" can be used as "key" for the $data array with
$data[array_keys($data)[0]]; // which is $data["ID"]; => "12345"
You can play with it online here: http://sandbox.onlinephpfunctions.com/code/4d6a4d86a6cdceccf4034fca06dcef9e50a89dc8
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);
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.
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);