Sorting simple Object [duplicate] - php

This question already has answers here:
Sort a flat, associative array by numeric values, then by non-numeric keys
(8 answers)
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
Base material :
I have a base list $food :
[{"id":"123","name":"apple"},{"id":"456","name":"Rost Beef"},...]
that i first reduce with $food_reduced = array_count_values(array_columns($food, "id"));.
[{123:2},{456:5},...]
Then i loop through $food_reduced with foreach($food_reduced as $id => $count) to query a DataBase to get the category (vegetables, fruits, meat, fish, etc..) that i store into $food_byCategory = array(); declared right before the loop :
if ($food_byCategory[$row["ctg_name"]])
{
$food_byCategory[$row["ctg_name"]] += $count;
}
else
{
$food_byCategory[$row["ctg_name"]] = $count;
}
Which gives me this array that I want to sort (gettype() says it's an Array at least) in PHP :
{
Vegetable: 2
Fruit: 1
Fish: 5
Drinks: 1
Meat: 2
Desert: 3
}
to this :
{
Fish: 5
Desert: 3
Meat: 2
Vegetable: 2
Drinks: 1
Fruit: 1
}
Notice the sorting by key once the sorting by value is done.
The goal is then to display this list into an html list by value descending.
I have tried asort, sort, arsort, with or without the option SORT_NUMERIC etc...
Wether it's not working at all or it's erasing the keys and replacing them with indexes.
I've also tried typecasting it into an array, but nothing changed (probably because it is an Array already ? But yet, not an Object ?)
I'm kinda lost.
Help ?
SOLVED my issue by building the "count" array another way :
if (!in_array($ctg_id, array_column($food_byCategory, "id")))
{
$food_byCategory[] = array(
"id" => $ctg_id,
"count" => 1
);
}
else
{
$index = array_search($ctg_id, array_column($food_byCategory, "id"));
$food_byCategory[$index]["count"]++;
}
and then sorting it with usort :
usort($food_byCategory, function($a, $b) {
return $b["count"] <=> $a["count"];
});

asort() applies to associative arrays, not objects.
You can easily transform your object into a associative array by typecasting it as describe here.
$array = (array) $yourObject;

You can use a php function called sort, try something like this:
$myArray = array(4, 6, 2, 22, 11);
sort($myArray);
result: 2, 4, 6, 11, 22
or
$myArray = array(4, 6, 2, 22, 11);
rsort($myArray);
result: 22, 11, 6, 4, 2

Related

Multiple values in array excluding specified key [duplicate]

This question already has answers here:
Deleting an element from an array in PHP
(25 answers)
Closed 9 months ago.
I'm trying to verify if certain values exist within an array excluding a specific key:
$haystack = array(
"id" => 1,
"char1" => 2,
"char2" => 3,
"char3" => 4,
);
$needles = array(2, 4);
Solution that I found here: in_array multiple values
function in_array_all($needles, $haystack) {
return empty(array_diff($needles, $haystack));
}
The problem is that I'm checking if certain chars exist within the array. This will work fine in this case:
$exists = in_array_all([2, 4], $haystack); // true
But it'll cause an issue in this situation:
$exists = in_array_all([1, 3], $haystack); // true
It found the value 1 in the key id and therefor evaluates as true while a char with id 1 is not within the array. How can I make it so that it excludes the key id within the search?
Note: This is example data. The real data is much larger, so just using if / else statements isn't really viable.
function in_array_all($needles, $haystack) {
return empty(array_diff($needles, $haystack));
}
function excludeKeys($haystack){
$tempArray = array();
foreach($haystack as $key => $value){
if ($key == "id"){
// Don't include
}else{
$tempArray[$key] = $value;
}
}
return $tempArray;
}
$haystack = array(
"id" => 1,
"char1" => 2,
"char2" => 3,
"char3" => 4,
);
$exists = in_array_all([1, 3], excludeKeys($haystack));
echo("Exists: ".($exists ? "Yes" : "No"));
This basically just returns the array without the keys you specify. This keeps the original array in tact for later use.
Edit:
These bad solutions are really a symptom of a problem in your data structure. You should consider converting your array to an object. It looks like this:
$object = new stdClass();
$object->id = 1;
$object->chars = array(2, 3, 4);
$exists = in_array_all([1, 3], $object->chars);
This is how you're supposed to separate your data up. This way you can properly store your information by key. Furthermore you can store other objects or arrays within the object specific to a key, as shown above.
Unset id index and then do search:
function in_array_any($needles, $haystack) {
unset($haystack['id']);
return !array_diff($needles, $haystack);
}
https://3v4l.org/PTjOS

Create sorted array from multiple pre-sorted arrays [duplicate]

This question already has answers here:
easier way to flatten or merge php array than this?
(2 answers)
Sort array by value alphabetically php
(4 answers)
Closed 6 months ago.
I would like to create a sorted array from a variable number of pre-sorted arrays.
Given {A1, ..., An} which are pre-sorted arrays, I would like to create At, which is the combination of {A1, ..., An} and is sorted in the same way.
Example :
Given :
A1 = [2, 4, 9, 16]
A2 = [-3, 4, 98, 116]
...
An = [1, 7, 17, 76, 512]
I would like :
At = [-3, 1, 2, 4, 4, 9, 16, 17, 76, 98, 116, 512]
What it is the most efficient way to compute this array ?
Thanks
It's simple. We have A1..AN - pre-sorted lists and same amount of indexes I1..IN set to zero (for zero-based lists). Now we need to form merged list from this. To do this we need to find smallest (or biggest depends on what's initial sort order) element from all these lists. It's obvious that this is one of the A1[I1] A2[I2] .. AN[IN] element. So we just go through all these elements and choose smallest. Let's say it was element in A2. We put it into our new big list and increment I2. Now we have same situation as in the beginning and should repeat all these steps again or stop if all lists exhausted.
Example:
A1 = [1, 2, 6]
A2 = [2, 4, 5]
A = []
I1 = 0
I2 = 0
-------------
A = [1]
I1 = 1
I2 = 0
-------------
A = [1, 2]
I1 = 2
I2 = 0
-------------
A = [1, 2, 2]
I1 = 2
I2 = 1
...
I have implemented a function doing what I want.
What do you think of the performance ? Do you have any advice to improve it ?
Sorting function:
function sortPreSortedArrays($arrays, $comparisonFunction, $order = 'asc')
{
$sortedArray = array();
/* Sort */
while(sizeof($arrays) !== 0)
{
/* Find the greatest value */
$max = true;
$keyMax = -1;
foreach($arrays as $key => $array)
{
if($max === true || $comparisonFunction(end($array), $max))
{
$max = end($array);
$keyMax = $key;
}
}
/* Take the greatest value */
array_push($sortedArray, array_pop($arrays[$keyMax]));
if(sizeof($arrays[$keyMax]) === 0) unset($arrays[$keyMax]);
}
/* Return */
if($order === 'asc')
return array_reverse($sortedArray);
else
return $sortedArray;
Comparison function:
function compareLogArrayDate($log1, $log2)
{
$t1 = $log1['date'];
$t2 = $log2['date'];
return ($t1 > $t2) ? true : false;
}
Edit: In order to improved the performancse, I have tried do use the most efficient array functions (array_pop O(1) instead of array_shift O(n). Nevertheless I am still using unset. :|
$A1 = [2, 4, 9, 16];
$A2 = [-3, 4, 98, 116];
$An = [1, 7, 17, 76, 512];
// create arrays of ith elements
$return = call_user_func_array('array_map', [null, $A1, $A2, $An]);
// sort arrays
array_walk($return, 'sort');
// create new arrays
$return = call_user_func_array('array_merge', $return);
// remove null values lefted after first operation
$return = array_filter($return, 'is_scalar');
var_dump($return);

Sort array by values ASC, then keys ASC [duplicate]

This question already has answers here:
Sort a flat, associative array by numeric values, then by non-numeric keys
(8 answers)
Closed 6 months ago.
SO,
The problem
I have an issue with custom array sorting. I have an array:
$rgData = [
3 => 1,
5 => 0,
1 => 2,
9 => 0,
0 => 1,
4 => 2,
2 => 1,
7 => 0,
6 => 0,
8 => 0,
];
-it contain keys with their counts (actually, it came after some operations with array_count_values). Now I want to sort it that:
Lower values comes first (i.e. usual ascending sort which can be done with asort())
Within one value, keys should be sorted ascending (here I need help)
For sample above result should be:
[5=>0, 6=>0, 7=>0, 8=>0, 9=>0, 0=>1, 2=>1, 3=>1, 1=>2, 4=>2]
My approach
I have no idea how to resolve this with sort by user-defined since usort or uasort accept only values for comparing while uksort - only keys and I need both of them in my comparison function. The only way that I have now - is to do this:
$rgData = ['3'=>1, '5'=>0, '1'=>2, '9'=>0, '0'=>1, '4'=>2, '2'=>1, '7'=>0, '6'=>0, '8'=>0];
$rgTemp = [];
asort($rgData);
$i = 0;
$mPrev = current($rgData);
foreach($rgData as $mKey=>$mValue)
{
$rgTemp[$mPrev==$mValue?$i:++$i][$mKey] = $mValue;
$mPrev = $mValue;
}
$rgTemp = array_map(function($rgX)
{
ksort($rgX);
return $rgX;
}, $rgTemp);
$rgData = [];
//can't use call_user_func_array('array_merge', $rgTemp) - it spoils numeric keys
foreach($rgTemp as $rgX)
{
foreach($rgX as $mKey=>$mValue)
{
$rgData[$mKey] = $mValue;
}
}
//var_dump($rgData);
-i.e. split array by values first, then do the stuff.
The question
How to do this in more easy way? I used asort + cycled ksort via array_map with final gathering loop. Temp array also used. It looks weird. I hope simpler method exists.
This should do what you want. It sorts by the keys, but we can access the value inside the function, so we can use that as our sort criteria too.
uksort($rgData, function($a, $b) use($rgData){
$aVal = $rgData[$a];
$bVal = $rgData[$b];
// Compare the values
if($aVal === $bVal){
// If they are the same, compare the keys
return $a - $b;
}
// Otherwise compare the values
return $aVal - $bVal;
});

Adding Across Arrays

I structured the item information in an unorthodox way, it is stored in three different arrays and are related by the key. I am looking to Sum the Quantities by ItemID.
1. Array #1 ItemID
$_SESSION["item_id"][]
1 => 1, 2 => 1, 3 =>2
2. Array #2 Size
$_SESSION["size"][]
1 => S, 2 => L, 3 =>S
3. Array #3 Quantity
$_SESSION["count"][]
1 => 250, 2 =>750, 3=>250
The result should be as follows:
ItemID # 1 --> Quantity 1000
ItemID # 2 --> Quantity 250
Could someone could help me with a function ?
Let's say, you have the following array in $_SESSION:
$_SESSION['item_id'] = array(1, 1, 2);
$_SESSION['size'] = array('S', 'L', 'S');
$_SESSION['count'] = array(250, 750, 250);
NOTE: the following answer take assumption that array length in those 3 SESSION value are equal.
You will need to create new array to store the result:
$newArrayResult = array();
After that, you will need to do for...each loop to extract currently accessed key:
foreach($_SESSION['item_id'] as $key => $value){
//the logic goes here
}
Next, we will use item_id as our array key in $newArrayResult. To do that, we will need to check first, if it is already defined. If not, create the key with default value 0. We do the checking by using built in function called array_key_exists. This way, we will avoid running into undefined key index error.
if(!array_key_exists($value, $newArrayResult)){
$newArrayResult[$value] = 0;
}
After we have the key for $newArrayResult, next step would be to simply store count value into it:
$newArrayResult[$value] += $_SESSION['count'][$key];
Done. Print the result to test:
print_r($newArrayResult);
Here is the whole code again, for you to copy-paste. Don't forget to read and understand the above flow first:
$_SESSION['item_id'] = array(1, 1, 2);
$_SESSION['size'] = array('S', 'L', 'S');
$_SESSION['count'] = array(250, 750, 250);
$newArrayResult = array();
foreach($_SESSION['item_id'] as $key => $value){
if(!array_key_exists($value, $newArrayResult)){
$newArrayResult[$value] = 0;
}
$newArrayResult[$value] += $_SESSION['count'][$key];
}
print_r($newArrayResult);

How to sort an array in php

i want the same value has the same index
for example
1 2 2 3 5
after sort:
array(
0=>1
1=>2
1=>2
3=>3
4=>5);
but we can not set duplicate index in the array of php.
There's a sort function in php! ( I answer the topic and not the body, didn't quite follow you there, but here's how you sort in php )
Example
<?php
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
echo "fruits[" . $key . "] = " . $val . "\n";
}
?>
Duplicates
In the above example duplicates will just have their own indexes so the array:
5 4 5 1 3 1 2
Will look like this
1 1 2 3 4 5 5
This might not be what you are looking for, what you want is another type of dataset than just a simple array, maybe you want a hashtable or just a linked list on each row.
If you are okay with it, you can remove the duplicates by using array_unique
$newArray=array_unique($arr);
Which would lead to having an array looking like this
1 2 3 4 5
You're right, you can't have duplicate values at the same index in an array - each index in an array has exactly one value.
As to the title of the question, to sort an array in PHP, use sort.
If this doesn't answer what you're trying to ask, you might want to edit your question to make it a bit clearer (the body of the question doesn't seem particularly related to the question title).
Post OP's edit:
You cannot store multiple values at the same key, your output array (array(0=>1, 1=>2, 1=>2, 3=>3, 4=>5);) doesn't really make sense (the key 1 does map to the value 2) in the sorted array. Are you trying to store counts of occurrences of numbers?
e.g. given the input:
1, 2, 2, 3, 5
get the output:
array(1=>1, 2=>2, 3=>1, 5=>1); // there is 1 "1", there are 2 "2"s etc.
Try to use this.
sort($array);
You are looking for array_unique:
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
Takes an input array and returns a new array without duplicate values.

Categories