How to organize items from an array in alphabetical order?

Asked

Viewed 2,456 times

1

I’m having a hard time organizing this array of mine:

$array = [];

$array[
        "T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama",
        "T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama",
        "T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb",
        "T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc",
        "T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd"
      ];

Each word of an item means something. For example in the item:T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz

T3497012 is the user id. CHOSTBRHDDSB is a host, EICM_BORA is a system, BPHS is a type and Bamz is a layer.

I need to sort all items in this array alphabetically, but there are some criteria:

alphabetical order first in systems resulting the array like this:

"T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd",
"T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc",
"T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb",
"T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama",
"T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama"

First the system AICM_BORA and lastly the EICM_BORA

Then I need to put it in order based on guy, being like this:

"T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd",
"T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc",
"T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb",
"T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama",
"T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama"

Now I do the same process and order for layer:

"T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd",
"T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc",
"T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb",
"T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama",
"T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama",
"T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz"

and lastly by hostname:

"T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd",
"T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc",
"T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb",
"T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama",
"T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama",
"T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",    
"T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
"T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz"

tried many things but I believe that my lack of experience does not allow me a solution to this.

  • But want to make an ordering based on 4 criteria or 4 different sorts ?

3 answers

4

You can use the usort(). I made for the layer:

function cmp($a, $b) {
    if ($a == $b) return 0;
    return (substr($a, 37, 4) < substr($b, 37, 4)) ? -1 : 1;
}

$array = [
        "T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama",
        "T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama",
        "T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb",
        "T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc",
        "T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd"
      ];
usort($array, "cmp");

foreach ($array as $key => $value) {
    echo "$key: $value\n";
}

I put in the Github for future reference.

If you are using a newer version you may not need to pass the name of the function but pass it directly, which can be more interesting. There’s an example in the documentation. You can probably even parameterize the initial and final column doing so without having to create a function for each key used.

There are some alternatives, but all the ones I’ve thought of look worse than this.

3


If each block between @ of the item means something so it is easier to start by separating these elements for an array with explode:

foreach ($array as $chave => $valor){
    $array[$chave] = explode("@",$valor);
}

Which will give you an array with the following look:

Array
(
    [0] => Array
        (
            [0] => T3497012
            [1] => CHOSTBRHDDSB
            [2] => EICM_BORA
            [3] => BPHS
            [4] => Bamz
        )

    [1] => Array
        (
            [0] => T3497012
            [1] => BHOSTBRHDDSB
            [2] => EICM_BORA
            [3] => BPHS
            [4] => Bamz
        )
    ...

Now that you have each separate part you can sort using usort which allows you to specify how it is sorted by means of a element comparison function:

usort($array, function($a, $b){
    if ($a[2] == $b[2]){ //posição 2 é o sistema
        if ($a[3] == $b[3]){ //posição 3 é tipo
            if ($a[4] == $b[4]){ //posição 4 é a camada
                return strcmp($a[1], $b[1]); //posição 1 é hostname
            }
            else return strcmp($a[4], $b[4]);
        }
        else return strcmp($a[3], $b[3]);
    }
    else  return strcmp($a[2], $b[2]);     
});

Note that the comparison of strings was made at the expense of the function strcmp.

Now to take back the string you can either join each element in a string when you need to use or even build the array you had with implode:

foreach($array as $chave => $valor){
    $array[$chave] = implode("@", $array[$chave]);
}

Example working on Ideone

Which gives the following result:

Array
(
    [0] => T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd
    [1] => T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc
    [2] => T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb
    [3] => T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz
    [4] => T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz
    [5] => T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz
    [6] => T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama
    [7] => T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama
)

Different from what had indicated right ? But this is the correct result for ordering us 4 criteria you indicated. Let’s try to better understand how it worked.

The first criterion is applied on the system, the AICM, EICM, etc. If repair they are ordered, with particular relevance to the fact of the EICM_BORC come after EICM_BORB and after EICM_BORA due to the last letter.

After the system ordering is applied we will apply the sort sort ordering only for those who have the same system the, 3 EICM_BORA. In this case they all have the same type BPHS, then we apply the sort by layer. The layer is also the same in 3 we pass to the last ordering criterion the hostname which is indeed different. Soon the 3 EICM_BORA were eventually ordered by hostname.

  • thanks a lot for the help, just wanted to understand why he started by normal in system and then the rest he did the opposite, started from b to a

  • @Juliohenrique Which one started from b to a ? the guys from EICM ?

  • Yeah, the guys in the building

  • @Juliohenrique It turns out that the first ordination is by the system, so the EICM go down, however, note that EICM_BORC comes after EICM_BORB and after EICM_BORA due to the last letter. The second ordering will only be applied to all elements that have the same system, which are the EICM_BORA, 3 total. These will now have another ordination applied, all others remain in the position they are in. And in these 3 both the type and the layer are equal so the sort by hostname

  • um truth, I’m sorry I didn’t notice at the end of the system names, thank you very much Isac you helped me a lot

2

You can do two for to sweep his array and put the if in the order of its criteria:

<?php
    $linhas = array(
        "T3497012@CHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@BHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@AHOSTBRHDDSB@EICM_BORA@BPHS@Bamz",
        "T3497012@AHOSTBRHDDSB@EICM_BORB@BPHS@Aama",
        "T3497012@AHOSTBRHDDSB@EICM_BORC@APHS@cama",
        "T2497123@DHOSTBRHDDSB@CICM_BORD@APHS@camb",
        "T2497123@EHOSTBRHDDSB@BICM_BORE@APHS@camc",
        "T5557012@FHOSTBRHDDSB@AICM_BORF@APHS@camd"
    );

    $i = 1;
    for ($i = 0; $i < (count($linhas) - 1); $i++){
        $linhai = explode("@", $linhas[$i]);
        for ($j = $i + 1; $j < count($linhas); $j++){
            $linhaj = explode("@", $linhas[$j]);

            $troca = false;
            if ($linhai[2] > $linhaj[2])
                $troca = true;
            else if (($linhai[2] == $linhaj[2]) && ($linhai[3] > $linhaj[3]))
                $troca = true;
            else if (($linhai[2] == $linhaj[2]) && ($linhai[3] == $linhaj[3]) && ($linhai[4] > $linhaj[4]))
                $troca = true;
            else if (($linhai[2] == $linhaj[2]) && ($linhai[3] == $linhaj[3]) && ($linhai[4] == $linhaj[4]) && ($linhai[1] > $linhaj[1]))
                $troca = true;

            if ($troca){
                $suporte = $linhas[$i];
                $linhas[$i] = $linhas[$j];
                $linhas[$j] = $suporte;
            }    
        }
    }

    var_dump($linhas);
?>

Exit:

array(8) {
[0]=> string(41) "T5557012@FHOSTBRHDSB@AICM_BORF@APHS@camd"
[1]=> string(41) "T2497123@EHOSTBRHDSB@BICM_BORE@APHS@camc"
[2]=> string(41) "T2497123@DHOSTBRHDSB@CICM_BORD@APHS@Camb"
[3]=> string(41) "T3497012@AHOSTBRHDSB@EICM_BORA@BPHS@Bamz"
[4]=> string(41) "T3497012@BHOSTBRHDSB@EICM_BORA@BPHS@Bamz"
[5]=> string(41) "T3497012@CHOSTBRHDSB@EICM_BORA@BPHS@Bamz"
[6]=> string(41) "T3497012@AHOSTBRHDSB@EICM_BORB@BPHS@Aama"
[7]=> string(41) "T3497012@AHOSTBRHDSB@EICM_BORC@APHS@bed"
}

See working

  • Roberto thank you very much for the answer, but the result is different from what I want, look in my question.

  • I made a change, now it’s all in alphabetical order

Browser other questions tagged

You are not signed in. Login or sign up in order to post.