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.
Related
Is this a good way to do this? If not what do you recommend?
The order is irrelevant as long as it is consistent. I also already know the values are not equal.
//We cannot know what types of data will be found here except that it is not a resource.
$element_array = [
$any_type_but_resource1,
$any_type_but_resource2,
$any_type_but_resource3,
$any_type_but_resource4,
$any_type_but_resource5,
$any_type_but_resource6
]
My initial solution: Serialize the values and use strcmp() but ensure that 0 can never be returned.
usort($element_array, static function($a, $b){
return strcmp(serialize($a), serialize($b));
);
You can see here https://3v4l.org/vRB65 that my sort works while the sort() does not. Does anyone have reason to suspect this will not always work?
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
I am sorting through an array using the usort function. The loop is working correctly as is the sorting (to some degree) however I seem to have missed something with regards to decimal places etc. My function is below
usort($this->view->blogs, 'comparison');
And here is the function. The function call works correctly and I can see I am returned sorted data
function comparison($a, $b)
{
return strcmp($a->cost_per_blog, $b->cost_per_blog);
}
The issue is with the actual sorting logic for instance I am returned a list like below
0.09724
0.58344
1.16688
12.05776
120.5776
126.60648
13.22464
132.63536
138.66424
168.80864
18.08664
18.08664
18.67008
180.8664
19.25352
21.10108
22.26796
the pattern continues... It appears that I am not taking into account the sorting of 3 digit numbers. I cant seem to think of what I am missing. Any help would be greatly appreciated.
Don't compare strings then, compare numbers:
return $a->cost_per_blog - $b->cost_per_blog;
You compare them as strings not as doubles.
One thing that's always bugged me (and everyone else, ever) about PHP is its inconsistency in function naming and parameters. Another more recent annoyance is its tendency to ask for function parameters by reference rather than by value.
I did a quick browse through the PHP manual, and found the function sort() as an example. If I was implementing that function I'd take an array by value, sort it into a new array, and return the new value. In PHP, sort() returns a boolean, and modifies the existing array.
How I'd like to call sort():
$array = array('c','a','b');
$sorted_array = sort($array);
How PHP wants me to call sort():
$array = array('c','a','b');
sort($array);
$sorted_array = $array;
And additionally, the following throws a fatal error: Fatal error: Only variables can be passed by reference
sort(array('c','a','b');
I'd imagine that part of this could be a legacy of PHP's old days, but there must have been a reason things were done this way. I can see the value in passing an object by reference ID like PHP 5+ does (which I guess is sort of in between pass by reference and pass by value), but not in the case of strings, arrays, integers and such.
I'm not an expert in the field of Computer Science, so as you can probably gather I'm trying to grasp some of these concepts still, and I'm curious as to whether there's a reason things are set up this way, or whether it's just a leftover.
The main reason is that PHP was developed by C programmers, and this is very much a C-programming paradigm. In C, it makes sense to pass a pointer to a data structure you want changed. In PHP, not so much (Among other things, because references are not the same as a pointer).
I believe this is done for speed-reason.
Most of the time you need the array you are working on to be sorted, not a copy.
If sort should have returned a new copy of the array then for each time you call sort(); the PHP engine should have copied the array into new one (lowering speed and increasing space cost) and you would have no way to control this behaviour.
If you need the original array to be not sorted (and this doesn't happen so often) then just do:
$copy = $yourArray;
sort($yourArray);
The reason I am asking this question is because I have landed my first real (yes, a paid office job - no more volunteering!) Web Development job about two months ago. I have a couple of associates in computer information systems (web development and programming). But as many of you know, what you learn in college and what you need in the job site can be very different and much more. I am definitely learning from my job - I recreated the entire framework we use from scratch in a MVC architecture - first time doing anything related to design patterns.
I was wondering what you would recommend as the best way to pass/return values around in OO PHP? Right now I have not implement any sort of standard, but I would like to create one before the size of the framework increases any more. I return arrays when more than 1 value needs to get return, and sometimes pass arrays or have multiple parameters. Is arrays the best way or is there a more efficient method, such as json? I like the idea of arrays in that to pass more values or less, you just need to change the array and not the function definition itself.
Thank you all, just trying to become a better developer.
EDIT: I'm sorry all, I thought I had accepted an answer for this question. My bad, very, very bad.
How often do you run across a situation where you actually need multiple return values? I can't imagine it's that often.
And I don't mean a scenario where you are returning something that's expected to be an enumerable data collection of some sort (i.e., a query result), but where the returned array has no other meaning that to just hold two-or-more values.
One technique the PHP library itself uses is reference parameter, such as with preg_match(). The function itself returns a single value, a boolean, but optionally uses the supplied 3rd parameter to store the matched data. This is, in essence, a "second return value".
Definitely don't use a data interchange format like JSON. the purpose of these formats is to move data between disparate systems in an expected, parse-able way. In a single PHP execution you don't need that.
You can return anything you want: a single value, an array or a reference (depending on the function needs). Just be consistent.
But please don't use JSON internally. It just produces unnecessary overhead.
I also use arrays for returning multiple values, but in practice it doesn't happen very often. If it does, it's generally a sensible grouping of data, such as returning array('x'=>10,'y'=>10) from a function called getCoordinates(). If you find yourself doing lots of processing and returning wads of data in arrays from a lot of functions, there's probably some refactoring that can be done to put the work into smaller units.
That being said, you mentioned:
I like the idea of arrays in that to pass more values or less, you just need to change the array and not the function definition itself.
In that regard, another technique you might be interested in is using functions with variable numbers of arguments. It is perfectly acceptable to declare a function with no parameters:
function stuff() {
//do some stuff
}
but call it with all the parameters you care to give it:
$x = stuff($var1, $var2, $var3, $var4);
By using func_get_args(), func_get_arg() (singular) and func_num_args() you can easily find/loop all the parameters that were passed. This works very well if you don't have specific parameters in mind, say for instance a sum() function:
function sum()
{
$out = 0;
for($i = 0; $i < $c = func_num_args(); $i++) {
$out += func_get_arg($i);
}
return $out;
}
//echoes 35
echo sum(10,10,15);
Food for thought, maybe you'll find it useful.
The only thing I'm careful to avoid passing/returning arrays where the keys have "special" meaning. Example:
<?php
// Bad. Don't pass around arrays with 'special' keys
$personArray = array("eyeColor"=>"blue", "height"=>198, "weight"=>103, ...);
?>
Code that uses an array like this is harder to refactor and debug. This type of structure is better represented as an object.
<?php
Interface Person {
/**
* #return string Color Name
*/
public function getEyeColor();
...
}
?>
This interface provides a contract that the consuming code can rely on.
Other than that I can't think of any reason to limit yourself.
Note: to be clear, associative arrays are great for list data. like:
<?php
// Good array
$usStates = array("AL"=>"ALABAMA", "AK"="ALASKA", ... );
?>