How do I remap my array keys using an array of integers? - php

Here is my original array of items
$items = [
0 => 'item 1',
1 => 'item 2',
2 => 'item 3'
];
I want to change the order of the items based on their keys, so I'm doing this...
$reorder = [2,0,1];
uksort($items, function($key1, $key2) use ($reorder) {
return (array_search($key1, $reorder) > array_search($key2, $reorder));
});
This works as it should, and produces the proper results.
$items = [
2 => 'item 3',
0 => 'item 1',
1 => 'item 2'
];
However, when returning that in Laravel as json the newly ordered $items reverts back to the original order, which is obviously not what I want.
Is there a way to remap the array keys while reordering them?

How exactly are you returning the array in Laravel? The following example works for me exactly as you want it.
Route::get('/test', function () {
$items = [
0 => 'item 1',
1 => 'item 2',
2 => 'item 3'
];
$reorder = [2,0,1];
uksort($items, function($key1, $key2) use ($reorder) {
return (array_search($key1, $reorder) > array_search($key2, $reorder));
});
return response()->json($items);
// {"2":"item 3","0":"item 1","1":"item 2"}
});
If you have tried it in a browser, keep in mind that some browsers automatically reorder json arrays. In that case you have to get the raw instead of the formatted data.

Related

How to loop through a list of products and categories on PHP

<?
$categoriesID = array("popular","old");
$product => array (
Product 1
'categoryID' => $categoriesID[1],
'Name' => 'Product One',
Product 2
'categoryID' => $categoriesID[2],
'Name' => 'Product Two',
Product 3
'categoryID' => $categoriesID[2],
'Name' => 'Product Two',
Product 4
'categoryID' => $categoriesID[2],
'Name' => 'Product Two',
);
How can I loop through this to reflect that product 1 belongs to category 1, product 2 belongs to category 2, product 3 belongs to category 2 and so on?
I tried the following but no luck..
foreach($product as $key => $pro){
var_dump($categoriesID[$key]);
}
I would really appreciated any suggestions or how what i'm doing wrong.The goal is to insert the relationship into a database table where in order to insert a product a category_id is required.
Your arrays are not written correctly. You got a multi dimensional array here (arrays inside of an array). Read this to understand how they are written and how you can work with them: http://php.net/manual/en/language.types.array.php
If your categories are numeric you should also consider to use numeric values: 1 instead of '1' inside of the $categoriesID array or depending on the database auto casting capability you will get issues inserting strings as decimals.
Here is your given code modified as working example. Ive changed the var_dump output for better readability of the result.
Ive also changed the array indexes you have used since arrays start at 0. If you need the numbers still to start at 1 you could add some nonsense value at the beginning of the array or subtract 1 when accessing the array. Keep in mind that this is an quick & dirty solution to the given problem.
Nevertheless as Patrick Q said you should consider some introduction to PHP.
<?php
$categoriesID = array('1','2');
$product = array (
array(
'categoryID' => $categoriesID[0],
'Name' => 'Product One',
),
array(
'categoryID' => $categoriesID[1],
'Name' => 'Product Two',
),
array(
'categoryID' => $categoriesID[1],
'Name' => 'Product Two',
),
array(
'categoryID' => $categoriesID[1],
'Name' => 'Product Two',
)
);
foreach($product as $key => $value){
echo var_export($value, true) . '<br>';
}
You could further edit Mariusz's answer to do something like this:
foreach($product as $item){
echo $item['Name'].' - '.$item['categoryID'].'<br>';
}
This would give you easy access to both product name and category ID.

Sorting by Subarray type value and then alphabetically

I have an array that looks something like this:
$array = [
'field1' => [
'#type' => 'text',
'#label' => 'Field 11',
],
'field4' => [
'#type' => 'fieldset',
'#label' => 'Field 4',
],
'field12' => [
'#type' => 'text',
'#label' => 'Field 12',
],
'field3' => [
'#type' => 'fieldset',
'#label' => 'Field 3',
],
'field18' => [
'#type' => 'text',
'#label' => 'Field 18',
],
];
I would like to sort this array in such a way where all the fields of type fieldset are at the bottom. At the same time, I would like the text fields (which are on top) to be sorted alphabetically by the #label and the fieldsets (which should be at the bottom) should also be sorted alphabetically by the label. This is what I had so far.
ksort($array);
uasort($array, function($field1) {
if ($field1['#type'] !== 'fieldset') {
return 0;
}
return 1;
});
Sorting the array by the key value successfully sorts my entire array alphabetically. But once I add the uasort, although my fieldset's are at the bottom, the alphabetical order is no longer present.
Any ideas?
Use usort with 2 conditions
usort($array, function ($i1, $i2) {
// compare types
$r = ($i1['#type'] == 'fieldset' ? 1 : 0) - ($i2['#type'] == 'fieldset' ? 1 : 0);
// if both are (or not) fieldset (r == 0), compare labels
return $r ? $r : strcmp($i1['#label'], $i2['#label']); } );
I would use array_multisort. This sorts as requested if you only have fieldset and text:
array_multisort(array_column($array, '#type'), SORT_DESC,
array_column($array, '#label'), SORT_ASC,
$array);
Extract all #type values into an array sort descending and extract all #label values into an array sort ascending, sorting the original.

MAX in PHP returning wrong value

I have an array with key and value pair. I'm building this array dynamically and below is the code.
$x[] = array('type_name' => $value->name,
'percentage'=> intval($percentage));
My intention is to get the maximum value and for that I do
max($x);
However it is returning the wrong value actually the lowest value. Following is my array. Any help would be awesome.
$x = array(
array(
'type_name' => 'type 1'
'percentage' => 10,
),
array(
'type_name' => 'type 2'
'percentage' => 15,
),
array(
'type_name' => 'type 3'
'percentage' => 45,
),
);
Thanks is advance.
From php max() documentation :
// Multiple arrays of the same length are compared from left to right
It means that if you want to compare "percentage" values first instead of "type_name" values, you'll have to change their order in the array.
So, you could build your array like this ("percentage" comes first) and it should work :
$x[] = array(
'percentage'=> intval($percentage),
'type_name' => $value->name
);
For example :
$x = array(
array(
'percentage' => 10,
'type_name' => 'type 1'
),
array(
'percentage' => 15,
'type_name' => 'type 2'
),
array(
'percentage' => 45,
'type_name' => 'type 3'
),
array(
'percentage' => 25,
'type_name' => 'type 4'
)
);
print_r(max($x));
Output :
Array
(
[percentage] => 45
[type_name] => type 3
)
Hope it helps.
You need to read how the max compares against different types of data. In your case, you are trying to compare against one of the array item i.e. percentage inside one of the item so the function max does not know to do this.
There is an example by Revo in the manual which shows you how to do this.
You are creating an array of arrays. max doesn’t know that your arrays should be compared by the 'percentage' key, so it can’t be used here.
Instead, find the maximum value yourself. For example, like this:
$maxPercentage = false;
foreach ($x as $item) {
if ($maxPercentage === false || $item['percentage'] > $maxPercentage) {
$maxPercentage = $item['percentage'];
}
}
Now, $maxPercentage will store maximum percentage. Of, if you want an item with maximum percentage, get it like this:
$maxPercentage = false;
$maxItem = false;
foreach ($x as $item) {
if ($maxPercentage === false || $item['percentage'] > $maxPercentage) {
$maxPercentage = $item['percentage'];
$maxItem = $item;
}
}

Algorithm to fetch nested array in PHP

This question doesn't necessarily have to be related to PHP or MongoDB.
I have MongoDB database with categories collection. Documents inside collection looks like below
{
title : 'Parent 1',
cat_id : '_ABC1',
level : 1
}
{
title : 'Parent 2',
cat_id : '_ABC2'
level : 1
}
{
title : 'Child 1',
cat_id : '_ABC1_CEF1'
level : 2
}
{
title : 'Child 2',
cat_id : '_ABC1_CEF2'
level : 2
}
{
title : 'Child Child 1',
cat_id : '_ABC1_CEF1_GHI1'
level : 3
}
{
title : 'Child Child 2',
cat_id : '_ABC1_CEF1_GHI2'
level : 3
}
Nesting
Now, what I want to do in PHP is get nested array(s) like
$array = array(
array(
'title' => 'Parent 1',
'cat_id' => '_ABC1',
'sub' => array(
'title' => 'Child 1',
'cat_id' => '_ABC1_CEF1',
'sub' => array(
array(
'title' => 'Child Child 1',
'cat_id' => '_ABC1_CEF1_GHI1'
),
array(
'title' => 'Child Child 2',
'cat_id' => '_ABC1_CEF1_GHI2'
)
)
)
),
...
...
)
For that I am using following algorithm (fetch nested level = N)
(N is a fetching parameter number that tells iterator, how deep array has to be fetched)
$array_holder = array();
foreach(MongoGetLevel1Cats as $parent){
$parent['sub'] = array();
foreach(MongoGetLevel2Cats as $child){
$child['sub'] = array();
foreach(MongoGetLevel3Cats as $child_child){
$child_child['sub'] = array();
...
...
array_push($child['sub'], $child_child);
}
array_push($parent['sub'], $child);
}
array_push($array_holder, $parent);
}
Return $array_holder;
As this function will give me the desired result but I don't have control over the deep nested level. If have to fetch nested level of order 100, I have to write foreach loop insider foreach loop for 100 times. Also I don't know performance wise this strategy will be good or not.
Does anybody have any idea how we solve this more strategically? Perhaps with for & foreach loop in combination which doesn't involve nesting foreach loop?
You can use a callback function. For example:
function add_two($result, $how_many_times)
{
$result = $result + 2;//adds 2
echo "current =".$result."<br>";
$how_many_times--;
if ($how_many_times>0)
{
$result = add_two($result, $n);
}
return $result;
}
$resultVar = add_two(5, 5);//should give 15...
echo "resultvar = ".$resultVar."<br>";//outputs: resultvar = 15
In the previous example, I am placing the same function add_two() inside itself and have created a conditional that sees how many iterations I want. Every time I iterate once, I subtract 1 value from $how_many_times. Once $how_man_times == 0, the add_two() function will no longer be called, and the result will have been obtained.
Similarly you can do the same thing with your code. There is no reason for you to have to rewrite the same function all over again if you can just call it inside itself.
Let me know if this is what you were looking for :)

Add a multidimension PHP Array at the end of each item of a multidimension array

Here are the two Multi-dimension arrays explained.
// Categories Array
$categories = array(
array('cat_id'=>'1', 'cat_name' => 'Category One', 'cat_data' => 'Some Data'),
array('cat_id'=>'2', 'cat_name' => 'Category Two', 'cat_data' => 'Some Data'),
array('cat_id'=>'3', 'cat_name' => 'Category Tree', 'cat_data' => 'Some Data')
);
// Products Array (One $products array is to be placed inside every new category.
$products = array(
array('p_id'=>'1', 'p_name'=>'Product One'),
array('p_id'=>'2', 'p_name'=>'Product Two'),
array('p_id'=>'3', 'p_name'=>'Product Three')
);
Here The $products needs to be placed inside every element of $category array, with a key of some random key take for eg 'product_list'.
Here is the result like
$category = array(
array('cat_id'=>'1', 'cat_name' => 'Category One', 'cat_data' => 'Some Data', 'product_list'=>array()),
array('cat_id'=>'2', 'cat_name' => 'Category Two', 'cat_data' => 'Some Data', 'product_list'=>array())
);
Please scroll Right for the above code to see the last element added to these elements.
Please tell how to add that multi-dimension array with a key to each n every element of the $category array. Thanks
What is the problem?
foreach ($categories as &$category) {
$category['product_list'] = $products;
}
Try to use this code.
foreach($categories as $key=>$value)
{
$categories[$key]['product_list'] = $products;
}
After trying several attemps, I solved this problem by myself by just a simple code. here it is.
$categories['product_list'] = $products;
Hope, users finding this type of problem this useful. Thanks

Categories