Jump to content

[SOLVED] usort help


mtylerb

Recommended Posts

Can someone explain to me what the parts 1 and 2 (below) of usort refer to?

 

usort($part1, array($part2, function-name));

 

I have tried looking up examples, but all I get is the same PHP manual example over and over, and they don't explain it very well.

Link to comment
Share on other sites

Lol, thanks ratcateme,

 

It was that 3rd example I was having problems with.  Especially after seeing:

 

usort($children, array($this, 'cmpVals'));

 

So this searches the array $children which is a part of whatever class using function cmpVals?

 

What if $children is an array of objects of type different than the class that we're currently in?

 

$children is currently returning an array of PageArchive Objects.  Like so,

 

Array
(
    [0] => PageArchive Object
        (
            [id] => 68
            [title] => Test 3
        )
    [1] => PageArchive Object
        (
            [id] => 37
            [title] => Test 1
        )
    [2] => PageArchive Object
        (
            [id] => 59
            [title] => Test 2
        )
    [3] => PageArchive Object
        (
            [id] => 72
            [title] => Test 4
        )
)

 

I'm wanting to sort the objects by their id's with no need to keep their top level keys.  So that it, instead, looks like:

 

Array
(
    [0] => PageArchive Object
        (
            [id] => 37
            [title] => Test 1
        )
    [1] => PageArchive Object
        (
            [id] => 59
            [title] => Test 2
        )
    [2] => PageArchive Object
        (
            [id] => 68
            [title] => Test 3
        )
    [3] => PageArchive Object
        (
            [id] => 72
            [title] => Test 4
        )
)

Link to comment
Share on other sites

As you are sorting on the first object var, a simple sort() will suffice

 

<?php
class page {
    private $id;
    private $title;
    
    function __construct ($t)
    {
        $this->id = rand(1,100);
        $this->title = $t;
    }
}

class book {
    private $pages;
    
    function __construct ()
    {
        for ($i=0, $t='A'; $i<10; $i++, $t++)
        {
            $this->pages[] =  new page ($t);
        }
    }
    
    function showPages ()
    {
        echo '<pre>', print_r($this->pages, true), '</pre>';
    }
    
    function sortPages ()
    {
        sort($this->pages);
    }
}

$foo = new book;
$foo->showPages();
$foo->sortPages();
$foo->showPages();

?>

Link to comment
Share on other sites

No, I'm not, I'm trying to sort according to $children->$vars where $vars is a choice of what they want to order by.  It might be id or it might be a date (created_on) that I eliminated for ease of reading.  I have it selecting the right var, but I can't get it to actually sort for me.  I'm grabbing 2 separate objects and merging them together, I then need to re-sort the newly merged entries.

 

It's for a plugin to give an RSS feed type searchability to a CMS.  Currently they have a find('/articles/archive'); I'm trying to expand that to adv_find(array('/articles/archive1','/articles/archive2'));

 

So the class itself is an extension of the original class, and uses the find() function available.  It then merges the 2 (or more) results into one array.  The last thing I need to do to complete this is sort and trim.

 

Sort all the newly merged entries by $vars

Trim the excess entries created by running 2 (or more) queries.

 

Sorry, I'm trying to explain as best I can.

 

Currently in my class, the search bit looks like:

 

<?php
class adv_find extends Page
{
public $search;
public $vars;
public $results;
public $sortAttribute;

public function sort($attribute,$children) 
{
	$this->sortAttribute = $attribute;
	usort($children, array($this, 'cmpVals'));
	return $this->parentArray;
}
     
private function cmpVals($val1, $val2) 
{
	$search = $this->sortAttribute;
	return strcasecmp($val1->$search, $val2->$search);
}

public function adv_where($search, $vars)
{
	/* 
	Build Variable $children
	*/

	$this->sort($sve['0'],$children);
	return $children;
}

public function __construct($search,$vars)
{
	// Instantiate all the variables necessary to do the search
	$this->search = $search;
	$this->vars = $vars;

	// Do the search and then save the results to $this->results
	$this->results = $this->adv_where($this->search,$this->vars);
}
}

function finder($query, $args = '')
{
$found = new adv_find($query, $args);
}

?>

 

I'm definitely no guru, but I'm trying.

Link to comment
Share on other sites

If it's useful at all, when I change the function cmpVals() to:

 

<?php

private function cmpVals($val1, $val2) 
{
	$search = $this->sortAttribute;
	print_r($val1->$search);
	echo "<br />"."\r\n";
	print_r($val2->$search);
	echo "<br />"."\r\n";
	echo strcasecmp($val1->$search, $val2->$search);
	echo "<br />"."\r\n";
	echo "<br />"."\r\n";
	return strcasecmp($val1->$search, $val2->$search);
}
?>

 

The values it outputs is:

 

2008-10-25 20:22:33
2008-10-25 20:18:29
1

2008-10-25 20:22:33
2008-10-25 20:17:49
1

2008-10-25 20:22:51
2008-10-25 20:22:33
2

2008-10-25 20:18:29
2008-10-25 20:17:49
1

 

Why is there a 2 in there?  This is my confused face.  Yes, ok, it looks a lot like my everyday face, but still.

Link to comment
Share on other sites

like this?

<?php
class page {
    private $id;
    private $title;
    
    function __construct ($t)
    {
        $this->id = rand(1,100);
        $this->title = $t;
    }
    
    function getVal($v)
    {
        return $this->$v;
    }
}

class book {
    private $pages;
    private $sortby;
    
    function __construct ()
    {
        for ($i=0, $t='A'; $i<10; $i++, $t++)
        {
            $this->pages[] =  new page ($t);
        }
    }
    
    function showPages ()
    {
        echo '<pre>', print_r($this->pages, true), '</pre>';
    }
    
    function sortPages ($sortby)
    {
        $this->sortby = $sortby;
        usort($this->pages, array($this, 'mycmp'));
    }
    
    function mycmp($a, $b)
    {
        $x = $a->getVal($this->sortby);
        $y = $b->getVal($this->sortby);
        return strcasecmp($x,$y);
    }
}

$foo = new book;
$foo->showPages();
$foo->sortPages('id');
$foo->showPages();
$foo->sortPages('title');
$foo->showPages();

?>

Link to comment
Share on other sites

Yes!  That's exactly it.  How is:

 

<?php

    function sortPages ($sortby)
    {
        $this->sortby = $sortby;
        usort($this->pages, array($this, 'mycmp'));
    }
    
    function mycmp($a, $b)
    {
        $x = $a->getVal($this->sortby);
        $y = $b->getVal($this->sortby);
        return strcasecmp($x,$y);
    }

?>

 

Different from mine?

 

<?php
public function sort($attribute,$children) 
{
	$this->sortAttribute = $attribute;
	usort($children, array($this, 'cmpVals'));
}
     
private function cmpVals($val1, $val2) 
{
	$search = $this->sortAttribute;
	return strcasecmp($val1->$search, $val2->$search);
}
?>

Link to comment
Share on other sites

Sorry, I was under the impression yours wasn't working so just adapted my first post. The only diff is my class had private vars, so I had to use getVal().

 

Re the 2, the manual says strcasecmp will return < 0, 0 or > 0, it doesn't have to be -1 or +1.

 

E.G. If you are comparing numeric items, the compare function can just be

 

function mycmp($a, $b) {return $a->something - $b->something;}

Link to comment
Share on other sites

Sorry, I was under the impression yours wasn't working so just adapted my first post.

 

It isn't, that's my problem.  When I try to sort using my function, the array doesn't change.  It stays in it's original form.  I tried sorting by title even, which gives a couple -1's:

 

Test Article 4
Test Article 2
2
title
Test Article 4
Test Article 1
3
title
Test Article 3
Test Article 4
-1
title
Test Article 2
Test Article 3
-1
title
Test Article 1
Test Article 2
-1

 

But it still doesn't change the order.  usort doesn't have to be saved, it automatically writes re-arranges the variable and it's permanent, correct?

Link to comment
Share on other sites

I am completely stumped.  I don't know if it's the input then, but assuming my functions (above) *should* work, am I doing something wrong with my input?

 

http://pastebin.com/m4a03e71e <- is the output of $children and what is being put in to be sorted

 

http://pastebin.com/m6ed560e6 <- is the full text of the class and it's following function, though not the class that it is extending.  There's a lot of extra print_r's in there to help me find the problem.

Link to comment
Share on other sites

you pass $children to sorty()

 

Then you copy $children to $this->children and sort that copy.

 

Right, that's what I'm doing at the moment.  That wasn't originally in there, I'm just trying anything and everything grasping at straws, hoping one of them won't be the short one.  I just can't understand why strcasecmp is evaluating them correctly, but usort isn't organizing them.  Could it be because the PageArchive Object was created by another class?  Do I need to do something with the usort function?

 

usort($children, array($this, 'cmpVals')

 

I'm still not sure what $this refers to or what it does to the usort function.  I have changed that to adv_find and tried Page (the class that adv_find extends) and PageArchive (the type of object), with no luck.

Link to comment
Share on other sites

Nope, still does nothing.  I really appreciate the help, any other ideas?

 

Can you explain what $this in:

 

usort($children, array($this, 'cmpVals'));

 

Does?  What does it refer to?  What changes if I change it?

Link to comment
Share on other sites

I've been up far too long, perhaps I'll see more after a good morning's sleep?  Thanks for all the help Barand, if you have any further ideas, I'll be checking back here later, and I'll be sure to try them out.

 

Same for anyone else, if you have any ideas, I'd love to hear and try them out.  Thanks in advance!

Link to comment
Share on other sites

$this refers to the current object

 

array ($this, 'cmpVals') refers to the the current object's class's "cmpVals" method.

 

so it tells usort() to use that particular function/method when comparing values.

 

 

But I am sure I am sure you problem lies in sorting a copy of the children array rather than the original, which is why the original always remains unchanged.

 

In my code the array to be sorted was a class var and therefore the same array is available to all the methods. You use $children which is local to the method, which is why I advised passing by ref so all functions use the same instance of the array

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.