Jump to content

What is the shortest way to compare 2 WireArrays?


valan
 Share

Recommended Posts

...and ideally fastest way.

Where "equal" means that both arrays have the same set of elements, while order may be different.

Straightforward way is to use double foreach, but I'm wondering if there is more elegant way with selectors and PW API.

Link to comment
Share on other sites

// could be this.
if(count(array_diff($array_1, $array_2)) === 0)) {
    echo "identical"
}

Others will come up with other clever ideas I think

It don't need to sort(), edited the post

don't take this as an example, 

Edited by Martijn Geerts
  • Like 4
Link to comment
Share on other sites

// could be this.
if(count(array_diff($array_1, $array_2)) === 0)) {
    echo "identical"
}

There is one ) too much, but it also gives a 500 Internal server error

edit: echo "identical" was missing ; that caused the 500 Internal error. It seems to work find when you remove on ) and add a ;

// could be this.
if(count(array_diff($array_1, $array_2)) === 0) {
echo "identical";
}

This one is not that short but will do the job

$wa1 = $pages->find('template=foo');
$wa2 = $pages->find('template=bar');
$wa3 = $pages->find('template=foo|bar,sort=name');
$wa4 = $pages->find('template=foo|bar,sort=-name');
$wa5 = $pages->find('template=foo|bar|foobar');

echo "compair: wa1 and wa2 = ";
echo count($wa1) >= count($wa2) ? count($wa1->not("id=$wa2")) : count($wa2->not("id=$wa1"));
echo "<br>";

echo "compair: wa3 and wa4 = ";
echo count($wa3) >= count($wa4) ? count($wa3->not("id=$wa4")) : count($wa4->not("id=$wa3"));
echo "<br>";

echo "compair: wa3 and wa5 = ";
echo count($wa3) >= count($wa5) ? count($wa3->not("id=$wa5")) : count($wa5->not("id=$wa3"));
echo "<br>";

Output (where 0 means identical)

compair: wa1 and wa2 = 3
compair: wa3 and wa4 = 0
compair: wa3 and wa5 = 9

(I have 3 pages with template foo, 3 with template bar and 3 with template foobar)

Edited by Raymond Geerts
  • Like 2
Link to comment
Share on other sites

Sorry Martijn, this one also outputs false while they are idential

$wa3 = $pages->find('template=foo|bar,sort=name');
$wa4 = $pages->find('template=foo|bar,sort=-name');

sort($wa3);
sort($wa4);

echo ($wa3 == $wa4) ? "true" : "false";

Altough the fly-thingies images are identical indeed :)

Link to comment
Share on other sites

Thank you guys! With correction (see http://us1.php.net/manual/en/function.array-diff.php) this seem to be the best option:

$a1 = $array_1->explode('id');
$a2 = $array_2->explode('id');
if((count(array_diff($a1, $a2)) + count(array_diff($a2, $a1)))===0) echo 'identical';

Would be great to see in PW core something like $a1->isIdentical($a2) as such kind of comparison is not rare (at least in my projects) !

Link to comment
Share on other sites

Works too (with WireArray/PageArray) the trick is to add the two arrays together, PW will remove dublicates. So you can compare count after "merging", if result is different they're not identical.

$orig = clone($a1);
if($a1->add($a2)->count == $orig->count) $is = "identical";

Edit: hmm, too soon. small correction, needs a clone to keep original array in memory

  • Like 4
  • Haha 1
Link to comment
Share on other sites

Just trying and while it works at first with two identical arrays, throwing in some different sorting it doesn't seem to work. Hmm.

Edit: I think it should work, but got some wierd result could be me aswell :) I think there's another simple way when dealing with page arrays but will test some.


Edit: Ah, I combined limit=N with sort... :)

  • Like 1
Link to comment
Share on other sites

Sorry, me again.

This works too and may best option with page arrays where you have an id.

if("{$a1->sort('id')}" == "{$a2->sort('id')}") echo "identical";

Sort them by id first and put into quotes to make them both a string, if string is same they were identical.

To go further, you could extend the PageArray with a new method. This can be done with a simple hook. For example in your templates init:

wire()->addHook("PageArray::compare", null, function($event){
    $a1 = $event->object;
    $a2 = $event->arguments(0);
    $event->return = "{$a1->sort('id')}" == "{$a2->sort('id')}";
});

Then you can use it everywhere in your templates like this

if($a1->compare($a2)) echo "identical";
If you the hook to an autoload module like the HelloWorld.module you could use this method throughout PW.
  • Like 6
Link to comment
Share on other sites


// This code should be in the docs, not because of this context,

// but because of the collaboration between $event->object and $event->arguments(0)

wire()->addHook("PageArray::compare", null, function($event){

$a1 = $event->object;

$a2 = $event->arguments(0);

$event->return = "{$a1->sort('id')}" == "{$a2->sort('id')}";

});

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...