I am trying to create an batch of similar array's based on first key of array.
Here is the input array
$headers = array(
0 => 'order_number',
1 => 'product_sku',
);
$input_array = array (
0 =>
array (
0 => '311000000706',
1 => 'S503053'
),
1 =>
array (
0 => '311000000706',
1 => 'S516135'
),
2 =>
array (
0 => '311000000703',
1 => 'S526587'
),
3 =>
array (
0 => '311000000703',
1 => 'S526587'
),
);
I am trying to create an seperate array if it has same order id like if two array has same order id = "311000000706"
then desired output will be
$desired_output = array (
0 =>
array (
0 => '311000000706',
1 => 'S503053'
),
1 =>
array (
0 => '311000000706',
1 => 'S516135'
));
Here is what i have tried
$prev_order_id_s = null;
$similar_order_ids = array();
foreach ($input_array as $key => $level):
if ($level['0'] == $prev_order_id_s) {
$similar_order_ids[][] = $level;
}
$prev_order_id_s = $level['0'];
endforeach;
but i am not getting desired output, i need some advice on this.
can you please advice some logic on this ?
Here is the compiler with above code - paiza.io/projects/fB-8CfiEuTX1cJXnXAZS3g
Instead of maintaining variables for previous order IDs, I would rather suggest you to take advantage of order ID as an associative key and keep adding rows to it whenever you find a matching order ID. In the end, you could array_values() on the collected data to remove order IDs as keys.
<?php
$set = [];
foreach($input_array as $row){
$set[$row[0]][] = $row;
}
$result = array_values($set);
print_r($result);
Do not use foreach to filter your array. You can use the array_filter function in PHP. Let's assume you want to check the first element of each array (means the zero index) and your desired value for this key is '311000000706'. It transaltes to PHP like this:
$desired_output= array_filter($input_array, function ($value) {
return $value[0] === '311000000706';
});
Related
I got this in my DB (23 is my picture ID):
{"23" : {"13x18":"5","20X30":"5","30x45":"4","digital":"4"}}
I want to add another data just like this one in the same spot so it would look like this :
["23" : {"13x18":"5","20X30":"5","30x45":"4","digital":"4"},
"42" : {"13x18":"2","20X30":"1","30x45":"3","digital":"1"}]
Here is the code is use :
$clientChoice = [];
$clientChoice[$post['picId']] = $test;
$select = (new GalleryCategoriesModel)->findByUrl($post['url']);
if($select['clientChoice'] != null){
$tabs = json_decode($select['clientChoice'], true);
$new = array_merge($tabs, $clientChoice);
$chosen = json_encode($new);
} else {
$chosen = json_encode($clientChoice);
}
$update = (new GalleryCategoriesModel)->update(['clientChoice'=>$chosen], $post['id']);
And here is the result i got with it :
[{"13x18":"5","20X30":"5","30x45":"4","digital":"4"},
{"13x18":"2","20X30":"1","30x45":"3","digital":"1"}]
What am I missing or doing wrong?
----------------- CORRECTION ------------------
Thanks to the answer given, here is what i do now :
$clientChoice = [];
$clientChoice[$post['picId']] = $test;
$select = (new GalleryCategoriesModel)->findByUrl($post['url']);
if($select['clientChoice'] != null){
$tabs = json_decode($select['clientChoice'], true);
$new = $tabs + $clientChoice;
$chosen = json_encode($new);
} else {
$chosen = json_encode($clientChoice);
}
$update = (new GalleryCategoriesModel)->update(['clientChoice'=>$chosen], $post['id']);
And here is what I got in my DB :
{"25":{"13x18":"1","20X30":"3","30x45":"5","digital":"1"},
"37":{"13x18":"4","20X30":"8","30x45":"3","digital":"2"}}
Your issue is with your call to array_merge. From the manual:
Values in the input arrays with numeric keys will be renumbered with incrementing keys starting from zero in the result array
So your two arrays that have keys of 23 and 42 end up merged as:
Array
(
[0] => Array
(
[13x18] => 5
[20X30] => 5
[30x45] => 4
[digital] => 4
)
[1] => Array
(
[13x18] => 2
[20X30] => 1
[30x45] => 3
[digital] => 1
)
)
You can work around this by using the array union operator (+), which will preserve the keys from both arrays (although it will ignore $clientChoice if the key is the same as one already existing in $tabs), however since they are id values I assume this should not occur.
$new = $tabs + $clientChoice;
In this case, $new contains:
Array
(
[23] => Array
(
[13x18] => 5
[20X30] => 5
[30x45] => 4
[digital] => 4
)
[42] => Array
(
[13x18] => 2
[20X30] => 1
[30x45] => 3
[digital] => 1
)
)
Demo on 3v4l.org
I have an array called $products.
If I perform a print_r of this array, I get the following output:
Array
(
[0] => Array
(
[0] => 2
[counter] => 2
[1] => Oranges
[item] => Oranges
)
[1] => Array
(
[0] => 3
[counter] => 3
[1] => Bananas
[item] => Bananas
)
[2] => Array
(
[0] => 1
[counter] => 1
[1] => Apples
[item] => Apples
)
[3] => Array
(
[0] => 1
[counter] => 1
[1] => Pears
[item] => Pears
)
)
I want to be able to list the item name which has the lowest 'counter' value, and if there are duplicate lowest counter values (like in the example above, apples and pears), then for only one to be chosen at random (must be randomly chosen).
Is anyone able to help me with this? Unfortunately I've not been able to find a suitable solution so far. Thanks in advance!
I would personally use usort in such a case, so that if two elements have the same counter you can foresee that later.
Besides, you can easily solve that issue from your mysql query, but here is how I would do this:
<?php
$products = array(
array(
"counter" => 2,
"item" => "Oranges"
),
array(
"counter" => 3,
"item" => "Bananas"
),
array(
"counter" => 1,
"item" => "Apples"
),
array(
"counter" => 1,
"item" => "Pears"
)
);
usort($products, function($previous, $next) {
return $previous["counter"] > $next["counter"] ? 1 : -1;
});
echo "Lowest counter is: {$products[0]['item']}";
?>
Explanation:
usort($products, function($previous, $next) {
return $previous["counter"] > $next["counter"] ? 1 : -1;
});
usort takes $products (the array) as the array to fetch and loops two items at a time (previous and next), the return statements check whether the previous element's counter is higher than the next one, if so, it puts it after it, else before it.
In the end, you will have the array elements sorted from the lowest counter one to the highest one.
I would suggest you, also, to later get the ones that have the same counter value if, such in this case, you have two elements which both are low, like this:
$products = array(
array(
"counter" => 2,
"item" => "Oranges"
),
array(
"counter" => 3,
"item" => "Bananas"
),
array(
"counter" => 1,
"item" => "Apples"
),
array(
"counter" => 1,
"item" => "Pears"
)
);
usort($products, function($previous, $next) {
return $previous["counter"] > $next["counter"] ? 1 : -1;
});
$lowest = $products[0]["counter"];
$filtered = array_filter($products, function($element) use ($lowest) {
return $element["counter"] === $lowest;
});
echo $filtered[array_rand($filtered, 1)]["item"];
working code:
https://3v4l.org/YPAeh
How about simplifying with the use of usort?
function compare_products($product1, $product2){
if($product1['counter'] == $product2['counter']){
return rand(0,1) ? 1 : -1//if it is the same then it is random
}
return $product1['counter'] > $product2['counter'];// if not it sorts the array
}
$products = ...;//your array
usort($products, "compare_products");
Then to get the lowest just do
echo $products[0];
Working example here (Idone) I simplified your array for the example
<?php
$products;//What ever you have assigned to this...
$size = count($products); // size of products array
$tmp = PHP_INT_MAX; // Set this to the highest possible counter value.
for($i = 0; $i < $size; $i++)
{
//If a new lowest counter has been found empty array and append this value
if($products[$i]["counter"] < $tmp)
{
$lowest = array();
$lowest[0] = $products[$i]["item"];
$tmp = $products[$i]["counter"];
}
//If counter is equally low append value
if($products[$i]["counter"] == $tmp)
{
$lowest[] = $products[$i]["item"];
}
}
echo array_rand($lowest);
?>
EDIT: Updated the code.
EDIT2: Addes Explanation below the code
This code works as follows:
The loop circels through the entire array. Which each step it checks whether the counter is lower then the one previously stored, initially the highest possible int value. If it is, the array with all wanted values is completely reset.
Next the loop checks whether the lowest value is the same as the previously stored "lowest" value. If so the item name is added to the array. In this way syou can collect all item names with the lowest value (one or more item names) in one array. If one smaller value occurs all item names before are not longer interesting and hence can be deleted. Once the loop has finished the function array_rand() outputs one random value, as you want it to. This is outputted as a string but can also be assigned to a variable.
I hope this helps to understand my code.
You want to get random minimum array from $data. For this you should do some following code.
$data[]=array
(
'0' => 2,
'counter' => 2,
'1' => 'Oranges',
'item' => 'Oranges'
);
$data[]=array
(
'0' => 3,
'counter' => 3,
'1' => 'Bananas',
'item' => 'Bananas'
);
$data[]=array
(
'0' => 1,
'counter' => 1,
'1' => 'Apples',
'item' => 'Apples'
);
$data[]=array
(
'0' => 1,
'counter' => 1,
'1' => 'Pears',
'item' => 'Pears'
);
$min=min(array_column($data, 'counter'));
$minarray=array();
foreach($data as $key=>$value) {
if($value['counter']==$min){
array_push($minarray,$value);
}
}
$rand_keys =array_rand($minarray);
echo"<pre>";
print_r($minarray[$rand_keys]);
Try this code on http://phpfiddle.org/ for online test.
I hope you will get solution.
This will take your $products and loop over each of them. Using the first element to set your currentLowest. If the value is a match it will add it to an array. If something less is found it will replace the currentLowest and remove the array values adding that value to a new one. At the end array_rand will give you a random index that you can use to access the lowValues.
<?php
//products is defined somewhere
$lowValues = array();
//Just to get it started
$currentLowest = $products[0]["counter"];
foreach($products as $product){
if($product["counter"] == $currentLowest){
//When Equal just add it
$lowValues[] = $product["item"];
} elseif($product["counter"] < $currentLowest) {
//When lower set as lowest
$currentLowest = $product["counter"];
//Remove all old values
unset($lowValues);
//Add this to the low values
$lowValues[] = $product["item"];
} else {
//Nothing to do here...
}
}
//array_rand is an index.
echo $lowValues[array_rand($lowest)];
?>
In a category overview, I need to sum all items that were studied in all the subcategories.
I have a function countitemsinsubcat() inside a foreach() that returns an array '$value' for each subcategory ($id_cat).
foreach ($subcategory as $row) {
$value =& countitemsinsubcat($id_cat);
$all_values_found [] = $value;
}
So these is $all_values_found for a category that has 2 subcategories:
Array (
[0] => Array(
[Istudied] => 0
[Itotal] => 1
)
[1] => Array (
[Istudied] => 1
[Itotal] => 4
)
)
In a category overview, I want to sum the values of the arrays of each subcategory, and get a 'total' array, like this:
Array
(
[Istudied] => 1
[Itotal] => 5
)
Any suggestions on how do this?
Have a look at this code snippet [PHP]:
//The magic happens here:
function concatit($v, $w)
{
$v[Istudied] += $w[Istudied];
$v[Itotal] += $w[Itotal];
return $v;
}
//Declaring the array.
$a = array (array(
Istudied => 0,
Itotal => 1
),array (
Istudied => 1,
Itotal => 4
)
);
//Making a call to the 'concatit' function declared above from within array_reduce.
$d = array_reduce($a, "concatit");
//Now $d contains the array as you wanted it.
echo $d[Istudied].' '.$d[Itotal];
Let me know if you need further clarifications! Enjoy!
I have the following array:
$list = array('item1','item2','item3','item4','item5','item6');
i need to take this array and break it into smaller arrays within 1 array for the csv. Each small array needs to have '999999' at index 0, followed by the next two items in the $list array. So the final result would be like this:
$newList = array(
array(999999, "item1" , "item2"),
array(999999, "item3" , "item4"),
array(999999, "item5" , "item6")
);
The original list array may contain up to 100 values at sometimes. What is the best way to achieve this?
Here's a different way of doing it, please see the comment as to where you place your additional elements to be prepended (you could add a second array into the merge at the end to add elements after the 2 list items too!)
See here for working example: http://codepad.org/hucpT5Yo
<?php
$list = array('item1','item2','item3','item4','item5','item6');
$list_chunks = array_chunk($list,2);
$list_chunks2 = array_map(
create_function(
'$x',
'return array_merge(array(
/* This array is prepended to the second,
add as many elements as you like */
999999,
"another element to add",
483274832
),
$x);'),
$list_chunks);
print_r($list_chunks2);
?>
$idx = 0;
$newarray = array();
$temparray = array('999999');
foreach($oldarray as $value) {
$temparray[] = $value;
if ((++$idx % 2)) == 0) {
$newarray[] = $temparray;
$temparray = array('999999');
}
}
Break your flat array into an array 2-element rows with array_chunk(), then call array_merge() on each row with the static value 999999 nested in an array and nominated as the first argument.
The modern syntax for the chunk-n-merge technique demonstrated by #Lee looks like this:
Code: (Demo)
$list = ['item1','item2','item3','item4','item5','item6'];
var_export(
array_map(fn($row) => array_merge([999999], $row), array_chunk($list, 2))
);
Output:
array (
0 =>
array (
0 => 999999,
1 => 'item1',
2 => 'item2',
),
1 =>
array (
0 => 999999,
1 => 'item3',
2 => 'item4',
),
2 =>
array (
0 => 999999,
1 => 'item5',
2 => 'item6',
),
)
Ok so i have a post that looks kind of this
[optional_premium_1] => Array
(
[0] => 61
)
[optional_premium_2] => Array
(
[0] => 55
)
[optional_premium_3] => Array
(
[0] => 55
)
[premium_1] => Array
(
[0] => 33
)
[premium_2] => Array
(
[0] => 36 )
[premium_3] => Array
(
[0] => 88 )
[premium_4] => Array
(
[0] => 51
)
how do i get the highest number out of the that. So for example, the optional "optional_premium_" highest is 3 and the "premium_" optional the highest is 4. How do i find the highest in this $_POST
You could use array_key_exists(), perhaps something like this:
function getHighest($variableNamePrefix, array $arrayToCheck) {
$continue = true;
$highest = 0;
while($continue) {
if (!array_key_exists($variableNamePrefix . "_" . ($highest + 1) , $arrayToCheck)) {
$continue = false;
} else {
highest++;
}
}
//If 0 is returned than nothing was set for $variableNamePrefix
return $highest;
}
$highestOptionalPremium = getHighest('optional_premium', $_POST);
$highestPremium = getHighest('premium', $_POST);
I have 1 question with 2 parts before I answer, and that is why are you using embedded arrays? Your post would be much simpler if you used a standard notation like:
$_POST['form_input_name'] = 'whatever';
unless you are specifically building this post with arrays for some reason. That way you could use the array key as the variable name and the array value normally.
So given:
$arr = array(
"optional_premium_1" => "61"
"optional_premium_2" => "55"
);
you could use
$key = array_keys($arr);
//gets the keys for that array
//then loop through get raw values
foreach($key as $val){
str_replace("optional_premium_", '', $val);
}
//then loop through again to compare each one
$highest = 0;
for each($key as $val){
if ((int)$val > $highest) $highest = (int)$val;
}
that should get you the highest one, but then you have to go back and compare them to do whatever your end plan for it was.
You could also break those into 2 separate arrays and assuming they are added in order just use end() http://php.net/manual/en/function.end.php
Loop through all POST array elements, pick out elements having key names matching "name_number" pattern and save the ones having the largest number portion of the key names. Here is a PHP script which does it:
<?php // test.php 20110428_0900
// Build temporary array to simulate $_POST
$TEMP_POST = array(
"optional_premium_1" => array(61),
"optional_premium_2" => array(55),
"optional_premium_3" => array(55),
"premium_1" => array(33),
"premium_2" => array(36),
"premium_3" => array(88),
"premium_4" => array(51),
);
$names = array(); // Array of POST variable names
// loop through all POST array elements
foreach ($TEMP_POST as $k => $v) {
// Process only elements with names matching "word_number" pattern.
if (preg_match('/^(\w+)_(\d+)$/', $k, $m)) {
$name = $m[1];
$number = (int)$m[2];
if (!isset($names[$name]))
{ // Add new POST var key name to names array
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
} elseif ($number > $names[$name]['max_num'])
{ // New largest number in key name.
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
}
}
}
print_r($names);
?>
Here is the output from the script:
Array
(
[optional_premium] => Array
(
[name] => optional_premium
[max_num] => 3
[key_name] => optional_premium_3
[value] => Array
(
[0] => 55
)
)
[premium] => Array
(
[name] => premium
[max_num] => 4
[key_name] => premium_4
[value] => Array
(
[0] => 51
)
)
)
Though ineffective, you could try something like
$largest = 0;
foreach($_POST as $key => $value)
{
$len = strlen("optional_premium_");
$num = substr($key, $len);
if($num > $largest)
$largest = $num;
}
print_r($largest);
The problem being that this will only work for one set of categories. It will most likely give errors throughout the script.
Ideally, you would want to reorganize your post, make each array be something like
[optional_premium_1] => Array
(
[0] => 61
["key"] => 1
)
[optional_premium_2] => Array
(
[0] => 61
["key"] => 2
)
Then just foreach and use $array["key"] to search.