Building an array of search parameters - php

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;
}

Related

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);

How to merge a flat array and a multidim array based on indexes and sum subarray column values?

There are two arrays:
$arr1 = [
"Value1",
"Value2",
"Value1"
];
$arr2 = [
["key_1" => "5", "key_2" => "10"], // relates to Value1
["key_1" => "2", "key_2" => "4"], // relates to Value2
["key_1" => "50", "key_2" => "100"] // relates to Value1
];
I cannot simply combine the two arrays because the duplicated values in $arr1 will lead to overwritten data from $arr2.
The behavior that I need is for subarray data to be added if a value from $arr1 is encountered more than once.
I tried to find all sorts of folding options while searching the web, but I could find anything that was right.
I need this output from the sample input arrays:
array (
'Value1' =>
array (
'key_1' => 55,
'key_2' => 110,
),
'Value2' =>
array (
'key_1' => '2',
'key_2' => '4',
),
)
I've tried to write a solution, but I'm not really sure how to tackle the problem.
foreach ($items as $item) {
if (isset($bal[$item['bonus_name']])) {
//Here I don't know how to sum a new one to the repetition?
} else {
$bal[$item['bonus_name']] = $item['bonus_count'];
}
}
Whatever I try, there's no way to sum a repetitive array of elements. I need some help.
Loop the first array to declare the index -> group relationship.
Check if the currently encountered group is unique to the output array. If so, push the entire subarray from the corresponding index in the second array into the output array as the initial values of the group.
If the group is encountered more than once, add each column value to the related amount in the group's subarray.
Code: (Demo)
$result = [];
foreach ($arr1 as $index => $group) {
if (!isset($result[$group])) {
$result[$group] = $arr2[$index];
} else {
foreach ($arr2[$index] as $key => $value) {
$result[$group][$key] += $value;
}
}
}
var_export($result);

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.

Split multidimensional array into arrays

So I have a result from a form post that looks like this:
$data = [
'id_1' => [
'0' => 1,
'1' => 2
],
'id_2' => [
'0' => 3,
'1' => 4
],
'id_3' => [
'0' => 5,
'1' => 6
]
];
What I want to achieve is to split this array into two different arrays like this:
$item_1 = [
'id_1' => 1,
'id_2' => 3,
'id_3' => 5
]
$item_2 = [
'id_1' => 2,
'id_2' => 4,
'id_3' => 6
]
I've tried using all of the proper array methods such as array_chunk, array_merge with loops but I can't seem to get my mind wrapped around how to achieve this. I've seen a lot of similar posts where the first keys doesn't have names like my array does (id_1, id_2, id_3). But in my case the names of the keys are crucial since they need to be set as the names of the keys in the individual arrays.
Much shorter than this will be hard to find:
$item1 = array_map('reset', $data);
$item2 = array_map('end', $data);
Explanation
array_map expects a callback function as its first argument. In the first line this is reset, so reset will be called on every element of $data, effectively taking the first element values of the sub arrays. array_map combines these results in a new array, keeping the original keys.
The second line does the same, but with the function end, which effectively grabs the last element's values of the sub-arrays.
The fact that both reset and end move the internal array pointer, is of no concern. The only thing that matters here is that they also return the value of the element where they put that pointer to.
Solution without loop and just for fun:
$result = [[], []];
$keys = array_keys($data);
array_map(function($item) use(&$result, &$keys) {
$key = array_shift($keys);
$result[0][$key] = $item[0];
$result[1][$key] = $item[1];
}, $data);
Just a normal foreach loop will do.
$item_1 = [];
$item_2 = [];
foreach ($data as $k => $v){
$item_1[$k] = $v[0];
$item_2[$k] = $v[1];
}
Hope this helps.

Counting Items Inside Multidimensional Associative 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);

Categories