ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
function ascORDER($x, $y)
{
if ( $x[0] == $y[0] )
return 0;
else if ( $x[0] < $y[0] )
return -1;
else
return 1;
}
Example usort:
usort($sdArray, 'ascORDER');
This works all fine and good, resorts the array by key position 0, or the name (Fred, Shaggy, Scooby). However if I want to change what I want to sort by, I have to go into ascORDER() and change the 0 to 1 or a 2 to change which key I want to sort by. This also works, but what I would like to do is rewrite the ascORDER() function to replace the hard coded key position to a variable as such:
function ascORDER($x, $y)
{
if ( $x[$z] == $y[$z] )
return 0;
else if ( $x[$z] < $y[$z] )
return -1;
else
return 1;
}
Where $z is the key position. Then I would simply like to pass with value of $z with:
usort($sdArray, 'ascORDER'); + ($z)
Obviously that isn't the solution, but does anyone have any idea how you can pass a variable to the user-defined comparison function (in this case ascORDER) when using usort?
Hi,
well you cant do that with usort because its interface is not thought to do that.
What you can do:
* Write a wrapper for usort, and then you can have two strategies: a function por each field you want to sort; or setting a global variable so you can get the key value inside your ascORDER function).
The first one would be something like:
There are a couple of solutions to your dilemma, that I can think of.
Have multiple sort functions - one for each dimension
Put it in a class and have a static variable point to the dimension you're interested in.
The first approach is the standard way to address these kind of problems, and with a little work you can get it to mirror the approach that you wanted to use, as indicated by demon_vox. The second avoid the use of global by wrapping it in a class but unless it is already in a class it is probably not worth the extra effort.
demonvox, I don't think the wrapper option would work for me since in addition to needing a $z variable field sort by, I also need this solution to be applicable to any number of fields in an array, the function needs to be able to work with an array with 3 fields or 10 fields etc. So hard coding a sortby function for each field sort by would be impossible. I did further pursue the global idea you suggested and came up with this:
<?php
$z=2;
function ascORDER($x,$y)
{
global $z;
if ( $x[$z] == $y[$z] )
return 0;
else if ( $x[$z] < $y[$z] )
return -1;
else
return 1;
}
This works and I can change $z to whatever I want and apply this to an array of any size. I am fairly new to globals, but I am interested in your warning about globals, what side effects would I be looking at here?
You also mentioned writing my own sorting algorthm, I thought about this as well, usort would be perfect if it simply supported passing a variable to the user-defined comparison function called within usort. I was wondering where I could find the code for usort, or how to even begin writing my own, any ideas, examples etc?
I don't think the multiple sort function option will for for me since I need to have the function be flexible enough to support arrays of any field size, so I wouldn't know from operation to operation how many sort functions I would need.
As you can see in the above post I did solve the problem using a global variable $z.
But there seems to be some kind of a negative stimga to using globals? Can your further elaborate on this, and let me know if you see any possible negative side-effects in my solution?
Also you had mentioned using classes to solve this problem? Can you further elaborate on how i might do this, and if that is a better solution than the globals?
The main problem with globals is if another piece of code also has a global with the same name, they will in fact be the same variable. So you have written some code using a global variable $z, then I could write some code which also used a global variable called $z, yours holds an array dimension mine holds the name of the favourite zoo animal.
If there is an overlap then the result is that my code stops your code from working, a side effect of my code changing your variable (and my variable). Because of the difficulty of working out why your code no longer works global variables are strongly discouraged.
Using a class provides you with a namespace, that it the $z will belong to your class. If I produce a $z in my class, because the classes will have separate names the $z will be different variables and there is no side effect.
I can definitely see what you are saying. As the project size increased with numerous developers just managing who's using what global would be a project in and of itself.
I have a very limited knowledge of class usage. How greatly will replacing the global $z with a class definied $z affect my existing code? Also, do you know of any good tutorials or examples I could use to switch my code from global usage to class usage?
hi,
well graemef told you about the side effects so I cant elaborate much more on that. I can only add a little detail of how you would use it.
If you are using global variables every time you want to sort an array with that method you would write:
Code:
$GLOBALS["z"] = 4;
usort($sdArray, 'ascORDER');
so, for sorting you will need two lines of code, being the first one extremely little declarative. If I have to read it I will trully wonder what the first line will do. Plus, you must never forget that line or you'll get unpredicting results. And catching this error es hard, but make this error is easy because you can just accidentaly erase the line by accident.
The Class solution that mentioned graemef is a good idea in theory but I dont see how to pass a method call as the usort second parameter (I tried it now but it doesnt seem to be working). If there is a way, then it's a good idea, but I just cant make it work :P
As regard of writing your own sorting function I meant to write it in PHP. If you want to hack the C code of PHP it is ok, but:
You need to know C
You will have to recompile PHP
You will only be able to use where this modify nonstandar PHP is installed
Yeah, the global solution works, I'm having my $z sort variable being passed via the browser and grabbing it up into the variable with a GET, but globals do seem like risky business. I have began investigating the class option, but I have much more reading until I have a good enough understand of classes to do something useful with them.
Am I possibly approaching this problem from the wrong angle? Is there a more standard way to sort an array variably by any of it's keys?
Hi,
what do you mean with "passing an array into a class"? What you do is pass the array as an method's argument of a class.
For instance:
Code:
class MyCoolClass {
function sort(&$anArray) {
// Here you do the magic with the array which is in the variable $anArray
print_r($anArray); //just for the sake of completeness
}
}
$myData = array("hola", "hello", "hi");
$mySorter = new MyCoolClass();
$mySorter->sort($myData);
That should work. Is this what you are trying to do?
function sortSTUFF($a)
{
function ascORDER($x,$y)
{
$z = (isset ($_GET['sortby'])) ? $_GET['sortby'] : 0;
if ( $x[$z] == $y[$z] )
return 0;
else if ( $x[$z] < $y[$z] )
return -1;
else
return 1;
}
usort($a, 'ascORDER');
return $a;
}
I know it's a bit hackish at this time, but $a is an array being passed in, and I got around the problem of passing a variable to the user-defined sort function used by usort, by simply defining $z with a get inside the user-defined sort function itself. I was also able to replace 'ascORDER' with a variable that would allow me to call any function. I am going to continue working on this looking more in the direction of a class solution, as it would be much cleaner. Thank you very much for all your help, I could never have gained as clear of an understanding of the picture without it.
Good thing you have it worked.
But just for the record, when you use the _GET array, you are still using a "global" variable. But in this case you are taking an array key ('sortby' in this case). Should you use a web page that has a link with this field in, and you try to sort an array, they will still colapse each other.
Since this is an "internal" variable, maybe it is better to have a name lika "__MyUsortVariable" or something like that, so you never step on it.
This is just a though, maybe it is useful, maybe not
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.