array_multisort with unexpected output - php

I have a function which has to handle a response from a SQL query. I have to reformat it into an array, reorder and return the new array. This is how I configure the array I want to sort
foreach($response as $key => $codigocentro ){
$centro = Centros::find($codigocentro);//another query using Phormium (this works fine)
$centro[$key]['da']= $centro->da;
$centrosAsignados[$key]['descrip'] = $centro->descrip;
$centrosAsignados[$key]['codigo'] =$codigocentro;
if (condition){
$centrosAsignados[$key]['orden_cs_cl'] = $centro->descrip;
$centrosAsignados[$key]['descrip_cabecera'] =$codigocentro;
}
}
After that I prepare the multiple filter as shown on the manual https://www.php.net/manual/en/function.array-multisort.php (example 3)
$array_da = array_column($centrosAsignados, 'da');
$array_cabec = array_column($centrosAsignados, 'descrip_cabecera');
$array_cs_cl = array_column($centrosAsignados, 'orden_cs_cl');
$array_descr = array_column($centrosAsignados, 'descrip');
For a final step:
array_multisort($centrosAsignados,
$array_da, SORT_DESC,
$array_cabec,
$array_cs_cl );
Now, I seem to have trouble ONLY with $array_cabec since the "da" or the "cs_cl" filters works as expected. The output respects those 2 successful conditions in the order I configured them.
I have outputted the results in many ways before and after, and I've closed the circle to my problem in this particular scenario (Output for these dumps in images below)
var_dump($array_cabec ); // to output initial values on this particular array
array_multisort($centrosAsignados, $array_cabec)
$array_cabec2 = array_column($centrosAsignados, 'descrip_cabecera');// reassigning values after sorting
var_dump($array_cabec2 ); // to output final values
I've already checked similar problems like
array_multisort not working properly?
Sort an array with special characters in PHP
How to sort an array of UTF-8 strings?
I've removed the entries with possible special characters and tried several encoding solutions like mb_convert_encoding, utf8_encode, utf8_encode+decode, iconv, trim , etc. With no results (at most I lose the special characters, but no difference in sorting)
The closest I got is the following
asort($array_cabec);
Which actually sorted the fields I need, but is not what I wanted.
I want the filters in array_multisort to apply one over another in a specific order.
I will show you the actual output (I'm using postman) of what I'm receiving at this moment:
Before the sorting:
After the sorting:
I'm expecting all the "C.S. ALGETE" to go in first place (C comes before D so DA_NORTE shouldn't go first). I don't know if I'm applying a right filter, if the flags I've tried should go in a different order or if there is another native function in php for achieving what I need.
For environment information I'm using php7 on windows and the DB where data comes from is coming from Informix database. If more information is needed please notice me in the comments. Information is reduced to ease reading, for example in the images where I haven't displayed all the 81 fields.
Please make sure it addresses my problem if you think this question is suitable for marking as duplicate.

After way too more research than expected i solved it with using USORT instead of array_multisort which I still think it has bugs when using strings. Which strings? -I still don't know (comment please if you do).
I dont need anymore the headers array. Usort plus annonymus functions with callbacks works perfect. (as it did with the asort) but i didnt figure out it could work with multidimensional.
usort($centrosAsignados, function ($a, $b){
$c = $a['da'] - $b['da'];
$c .= strcmp( $a['descrip_cabecera'], $b['descrip_cabecera']);
$c .= $b['orden_cs_cl'] - $a['orden_cs_cl'];
$c .= strcmp( $a['descrip'], $b['descrip']);
return $c;
} );
EDIT: You can trade $a with $b to get ascending or descending order for any of the applied filters. For example:
$a['da'] - $b['da']; => $b['da'] - $a['da'];
Collateral credits to sleipnir214 in
https://www.tek-tips.com/viewthread.cfm?qid=690382
and Nsisodia91 from user contribution in php manual (this answer is a bit below)
https://www.php.net/manual/en/function.usort.php

Related

I need to change the php code in the file so instead of the current json output

So i am using this PHP code to create the json output, and I am having an issue where it’s creating an array of array with the info. I would like to get rid of one array and just display the list of API’s thats been used and number that has been used.
Looks as though the difference is you have...
"apis":[{"item_search":"0\n"},{"item_recommended":"0\n"}]
and want
"apis":{"item_search":"0\n","item_recommended":"0\n"}
If this is the case, you need to change the way you build the data from just adding new objects each time to setting the key values directly in the array...
$zone_1 = [];
foreach($zone_1_apis as $api_name ) {
$zone_1[substr($api_name, 0,-5)] = file_get_contents('keys/'.$_GET['key'].'/zone_1/'.$api_name);
}
You also need to do the same for $zone_2 as well.
It may also be good to use trim() round some of the values as they also seem to contain \n characters, so perhaps...
trim(file_get_contents('keys/'.$_GET['key'].'/zone_1/'.$api_name))

PHP Sort Complex Array

Instead of working with mysql data, I have created csv file that I plan to use as the source of data for content, etc.
And I have successfully been able to parse the csv and store it into a complex array, that has the following header row aka the keys for the arrays.
"Title","Year","Rated","Released","Runtime","Genre","Director","Writer","Actors","Plot","Language","Country","Awards","Poster","Metascore","imdbRating","imdbVotes","imdbID","Type","Response"
My current stage is to allow dynamic ajax sorting of the arrays.
I have two fields, that I am allowing sorting at the beginning, "Year" and "Title".
So I pass different url paramters, such as "yearasc" or "yeardesc" or "titleasc" or "titledesc".
Then try to sort for that.
So what I did reading a different so post, was to do this.
First I create new arrays that only store the key fields, I need for sorting.
Then based on what sort type, do a different array_multisort.
array_multisort($year, SORT_ASC, $all_rows);
But what I get is results that multiple dupplicate data.
But I wonder if having the first row, be the header row, which is required by the function I pass the data after any sorting to, is causing issues with array sorting.
For simple array sorting, existing functions makes sense and work fine.
But for complicated ones, it is just complex to even understand how to approach solving this problem.
Any suggestions, thoughts or ideas are appreciated and thanked.
Thank you!
I don't have the actual code that is probably going to help you, but I do have a suggestion as for how you can tackle this and make it work..
Keep it simple. First, create your own CSV with just 1 header (Year or Title ) that you want to sort on.
Write your code to sort on that.
Then, add the other one ( Title if you used Year before, or Year if you used Title before ) and sort on whichever you want.
Then, add one more header (say, Rated) that you don't want to sort on.
You should then be able to work with the original CSV.
I'd try to write simple methods and keep your processing to a minimum in each one.
I hope that helps. I realize its more philosophical of an answer, so it is hit or miss if it helps you get the job done. Just realize that this approach will, indeed, take a little more time to write - but the point behind it is that you're taking out all of the "noise" that's getting in your way first. It helps you look at only your problem first and solve that.
You can set a custom sort function to the array. Use asort() if you need to keep original array keys.
<?php
$sortfields = array('year', 'bleh');
function cmp($a, $b) {
global $sortfields;
foreach ($sortfields as $sortfield) {
$cmp = strcmp($a[$sortfield], $b[$sortfield]);
// if desc, invert sign of $cmp
if ($cmp !== 0)
return $cmp;
}
return 0;
}
usort($all_rows, "cmp");
The function usort() calls a user defined comparison function, which returns the same logic from strcmp function: 0 if equal, < 0 is $a is less than $b and > 0 if $a is greater than $b.
This function will compare each field set in $sortfields variable, if it find any comparison that is different (in the order set), it will immediately return the difference.

alphanumeric sorting with php and preg_match

I have an array called $itemArray[] that contains a set of strings, such as:
myItem_1,
myItem_2,
myItem_3,
myItem_4,
anotherName_1,
anotherName_2,
anotherName_3,
anotherName_4
I also have the following code that goes through the array and filters out the ones that contain 'myItem'.
The loop works, however, it returns results in varied order. Is there a way to sort the result of the array so
that it lists them alphanumerically?
foreach($itemArray as $item) {
if (preg_match('/myItem/',$item))
echo '$item';
}
I don't have much experience with php and would definitely appreciate the help! Thank you!
PHP supports lots of ways to sort arrays, see how they work here. You could run it as asort($itemArray).
The right way to solve this is by sorting the array prior to outputting it. Something along the lines of:
asort($itemArray);
foreach($itemArray as $item) {
if (preg_match('/myItem/',$item))
array[index++] = $item;
}

PHP Array: Is there a way to force all array keys to be string?

Edit: I have made a demo to my problem: http://codepad.org/ByNdAdCI
We use the following logic to set our arrays in 32 bit php:
private function formatAvailableOptions($availableOptions) {
$optionsAsArray = array();
foreach($availableOptions as $option){
$optionsAsArray[$option["entity_id"]] = $option["name"];
}
return $optionsAsArray;
}
Problem:
The $option["entity_id"] has grown too big to fit in 32 bit int, and as a result overflow when $optionsAsArray gets created. For example
$optionsAsArray[2147483648] = "hi";
becomes
$optionsAsArray[-2147483648] = "hi";
I need the index to be 2147483648 as it's tied to ids in the database
This code is already shipped to the client, and the logic is used in many places that makes it infeasible to modify every single instance to
$optionsAsArray[strVal(2147483648)] = "hi";
to make it run properly by using string type as key to associative array.
What is the best solution in this case? Is there a global config option for me to force all php arrays to use string as keys to get around this problem?
Seems, that it doesn't like floats as keys ;) So the type cast to float fails. You already mentioned your solution in the question (strVal($var), or (string) $var, or just "$var"). If your customers run PHP in 64bit (what they should ;)) they don't see any difference. Because this is obviously a bug you should consider to fix it and publish an update to your customers. There is no option, or setting, that converts a 32bit installation into a 64bit one on the fly.

PHP Change Array Over and Over

I have any array
$num_list = array(42=>'0',44=>'0',46=>'0',48=>'0',50=>'0',52=>'0',54=>'0',56=>'0',58=>'0',60=>'0');
and I want to change specific values as I go through a loop
while(list($pq, $oin) = mysql_fetch_row($result2)) {
$num_list[$oin] = $pq;
}
So I want to change like 58 to 403 rather then 0.
However I always end up getting just the last change and non of the earlier ones. So it always ends up being something like
0,0,0,0,0,0,0,0,0,403
rather then
14,19,0,24,603,249,0,0,0,403
How can I do this so it doesn't overwrite it?
Thanks
Well, you explicititly coded that each entry should be replaced with the values from the database (even with "0").
You could replace the values on non-zero-values only:
while(list($pq, $oin) = mysql_fetch_row($result2)) {
if ($pq !== "0") $num_list[$oin] = $pq;
}
I don't get you more clear, i thought your asking this only. Check this
while(list($pq, $oin) = mysql_fetch_row($result2)) {
if($oin==58) {
$num_list[$oin] = $pq;
}
}
In my simulated tests (although You are very scarce with information), Your code works well and produces the result that You want. Check the second query parameter, that You put into array - namely $pg, thats what You should get there 0,0,0,0,0...403 OR Other thing might be that Your $oin numbers are not present in $num_list keys.
I tested Your code with mysqli driver though, but resource extraction fetch_row is the same.
Bear in mind one more thing - if Your query record number is bigger than $numlist array, and $oin numbers are not unique, Your $numlist may be easily overwritten by the folowing data, also $numlist may get a lot more additional unwanted elements.
Always try to provide the wider context of Your problem, there could be many ways to solve that and help would arrive sooner.

Categories