-1

EDIT: I rewrote my post in order to be clearer and provide a standalone case with real values (no Ajax anymore).

I have 2 arrays that are exactly identical except that one has the same values but cleaned (html, special chars, etc..).

I would like to evaluate the sorting against "arrayClean" but to sort "arrayOriginal" instead (not arrayClean) according to that evaluation.

So, this is what I have:

<?php

$arrayOriginal  = array(
    array('id' => '100','surface' => '<span>300</span>','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100 ch','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '<b>1000</b>','whatever' => 'fgsdfg')
);

$arrayClean = array(
    array('id' => '100','surface' => '300','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '1000','whatever' => 'fgsdfg')
);

usort($arrayOriginal, function($a, $b) use (&$arrayClean) {
    return $a['surface'] < $b['surface'];
});

echo '<pre>'; print_r($arrayOriginal); echo '</pre>';

?>

here is what I get (which is wrong as the arrayClean doesn't seem to be taken into account for the sorting) :

Array
(
[0] => Array
    (
        [id] => 100
        [surface] => <span>300</span>
        [whatever] => qSDqsd
    )

[1] => Array
    (
        [id] => 40489
        [surface] => <b>1000</b>
        [pwhatever] => fgsdfg
    )

[2] => Array
    (
        [id] => 5465
        [surface] => 100 ch
        [whatever] => ghjkghjk
    )

)

But if I use arrayClean alone, just to check if the sorting script is right:

usort($arrayClean, function($a, $b) {
    return $a['surface'] < $b['surface'];
});

echo '<pre>'; print_r($arrayClean); echo '</pre>';

Then the result is what I expect it to be:

Array
(
[0] => Array
    (
        [id] => 40489
        [surface] => 1000
        [whatever] => fgsdfg
    )

[1] => Array
    (
        [id] => 100
        [surface] => 300
        [whatever] => qSDqsd
    )

[2] => Array
    (
        [id] => 5465
        [surface] => 100
        [whatever] => ghjkghjk
    )

)

So it seems that evaluating arrayClean but sorting arrayOriginal accordingly doesn't work. It only evaluates AND sort arrayOriginal. Do I use "use()" wrong ? Should I use something else ?

Thank you.

Bachir Messaouri
  • 754
  • 2
  • 8
  • 31
  • 2
    because when you use `use` closure it pass it by value so to pass it by reference try to add `&` before `array` name to be like this `use(&$arrayClean)` – Joseph Apr 08 '20 at 01:26
  • Thank you. I tried your proposition by adding "&" before the array in the use() closure, but I get the exact same result than before. – Bachir Messaouri Apr 08 '20 at 01:40
  • Actually, I edited my initial post: with or without your proposition, arrayOriginal is sorted actually, but not like the arrayClean is (if I sort it alone). It sorts arrayOriginal the usual way, without taking arrayClean into account. – Bachir Messaouri Apr 08 '20 at 02:22

3 Answers3

1

Assuming both arrays are sorted by a common factor (i.e. id).

uksort($arrayOriginal, function($a, $b) use ($arrayClean) {
    return $arrayClean[$a]['surface'] < $arrayClean[$b]['surface'];
});

Emphasising once more, to make it work, both arrays MUST contain elements in the same order. In your case elements of both arrays MUST come in the following order (by id): 100, 5465, 40489

BUT I'd rather do something like:

usort($arrayOriginal, function($a, $b) {
    return yourSurfaceCleanMethod($arrayOriginal['surface']) < yourSurfaceCleanMethod($arrayOriginal['surface']);
});

All depends on your needs, of course, but if you are using $arrayClean only as a reference for sorting original array and you have that yourSurfaceCleanMethod handy, I'd definitely do the above.

Nemoden
  • 8,816
  • 6
  • 41
  • 65
  • I tested the script . It doesn't work outside this test use case (I know you're not supposed to extrapolate). The uksort sorts the arrayOrginal alright but the array indexes remain. Before the sorting, I have Array(Array[0](s=300),Array[1](s=100),Array[2](s=1000)). After, I get Array(Array[2](s=1000),Array[0](s=300),Array[1](s=100)). But I need to sort the content and reassign the array indexes like this: Array(Array[0](s=1000),Array[1](s=300),Array[2](s=100)). Otherwise, exporting this array (AJAX) just reorders the indexes and I end up with the same array I had in the first place. – Bachir Messaouri Apr 08 '20 at 04:03
  • I will consider this as a valid answer eventually because you technically answered to the scope of the test use case. But I haven't accepted your answer yet so that I can get people's attention in order to solve my actual problem. Thank you very much for all the help you already provided so far. – Bachir Messaouri Apr 08 '20 at 04:53
  • @BachirMessaouri `in order to solve my actual problem ` - what's you *actual* problem then? Answering your questions: no, you don't use `use wrong`, it's your logic inside the callback doesn't do what needs to be done. Should you use something else? maybe, in programming there is no "the only way", but doing what you are trying to do is perfectly okay. – Nemoden Apr 09 '20 at 02:48
  • @BachirMessaouri oh, okay, I see your comment above... And i don't quite understand what you are trying to achieve with those ids.... the original question didn't mention it has anything to do with the ids, just sorting by `surface`. You might want to update your question providing inputs and expected output. – Nemoden Apr 09 '20 at 02:52
  • That is okay Nemoden. You have been very helpful as it gave me a good start to understand what is going on. I found the solution eventually and I updated my post accordingly. But just for you to know, When I say, I want ID's to be updated, I didn't say I want to sort according to the key "Id". I meant I want to sort by surface but eventually, if the surface sorting is 1000, 300 100, I want the ARRAY indexes to be Array(Array[0](s=1000),Array[1](s=300),Array[2](s=100)). I'm not sorting the ARRAY indexes, I'm saying that index 0 is 1000, index 1 is 300 and index 2 is 100. – Bachir Messaouri Apr 09 '20 at 02:59
  • I tried to made it clear that I was taking about the ARRAY indexes not the key "id" but it seems I wasn't clear enough. I hope the answer I added will make it cristal clear. Don't hesitate to give your opinion. Anyway, I accepted your answer because it technically answered my question according to the information I brought. Thank you ! – Bachir Messaouri Apr 09 '20 at 03:21
0

I think the arrayClean is not needed if your arrayOriginal should be sorted according to the content of the HTML tags.

strip_tags() can be used for this in your sort function.

usort($arrayOriginal, function($a, $b) {
    return strip_tags($b['surface']) <=> strip_tags($a['surface']);
});

Note: Use the spaceship operator <=> to get correct comparison results 1, 0 and -1.

jspit
  • 7,276
  • 1
  • 9
  • 17
0

I accepted Nemoden's answer as a courtesy because technically it answered the question according to its scope (the test case as presented). But here is the solution I found that works best for me :

$arrayOriginal  = array(
    array('id' => '100','surface' => '<span>300</span>','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100 ch','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '<b>1000</b>','whatever' => 'fgsdfg')
);

$arrayClean = array(
    array('id' => '100','surface' => '300','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '1000','whatever' => 'fgsdfg')
);

$surface = array_column($arrayClean, 'Surface');

array_multisort($surface, SORT_DESC, SORT_REGULAR, $arrayOriginal);

And then I get this output, which is EXACTLY what I want:

Array
(
    [0] => Array
        (
            [id] => 40489
            [surface] => <b>1000</b>
            [whatever] => fgsdfg
        )

    [1] => Array
        (
            [id] => 100
            [surface] => <span>300</span>
            [whatever] => qSDqsd
        )

    [2] => Array
        (
            [id] => 5465
            [surface] => 100 ch
            [whatever] => ghjkghjk
        )

)

The answer of Nemoden was very helpful BUT it gave me this, for whatever reason:

Array
(
    [1] => Array
        (
            [id] => 40489
            [surface] => <b>1000</b>
            [whatever] => fgsdfg
        )

    [0] => Array
        (
            [id] => 100
            [surface] => <span>300</span>
            [whatever] => qSDqsd
        )

    [2] => Array
        (
            [id] => 5465
            [surface] => 100 ch
            [whatever] => ghjkghjk
        )

)   

The sub arrays are PRINTED in the right order but the sub arrays indexes weren't changed. So when exporting to javascript "arrayOriginal", it would come back to its initial sorting because the sub arrays would be re-ordered according to their indexes again. At least, that's what I experienced.

Anyway, now the problem is solved and the answers I got here were very helpful.

Thank you.

Bachir Messaouri
  • 754
  • 2
  • 8
  • 31