How to organize items in an array in alphabetical order?

1

I'm having a hard time organizing this array:

$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,   however there are some criteria:

alphabetical order first in the systems resulting in 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 finally the EICM_BORA

Then I need to put in order based on type , thus:

"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 I command by 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 finally 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"

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

    
asked by anonymous 21.01.2018 / 21:51

3 answers

3

If each block between @ of the item means something then it is easiest to start by separating these elements into an array with explode :

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

That 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 do the sorting using usort that allows you to specify the way it is ordered through a function of comparing the elements:

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 string comparison was done at the expense of strcmp .

Now to get back to the string you have both you can join each element in a string when you need to use or even re-build the array you had with implode :

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

Example working on Ideone

That 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 I had indicated right? But this is the correct result for the ordering in%% of criteria you indicated. Let's try to better understand how it worked.

The first criterion is applied to the system, 4 , AICM , etc. If they are repaired they are sorted, with particular relevance to the fact that EICM comes after EICM_BORC and then EICM_BORB due to the last letter.

After sorting by the system we will apply sorting by type only for those with the same system , EICM_BORA 3 . In this case they all have the same type EICM_BORA , so we start to apply sorting by the layer. Since the layer is also equal in the BPHS we pass to the last sort criterion the 3 which is in fact different. Then the hostname 3 ended up ordered by EICM_BORA .

    
21.01.2018 / 22:30
3

You can use usort() . I made it to 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";
}

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

There are a few alternatives, but all of the ones I thought seem worse than this one.

    
21.01.2018 / 22:19
1

You can make two for to sweep your array and put if in the order of your 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);
?>

Output:

  

array (8) {
  [0] = > string (41) "T5557012 @ FHOSTBRHDDSB @ AICM_BORF @ APHS @ camd"
  [1] = > string (41) "T2497123 @ EHOSTBRHDDSB @ BICM_BORE @ APHS @ camc"
  [2] = > string (41) "T2497123 @ DHOSTBRHDDSB @ CICM_BORD @ APHS @ camb"
  [3] = > string (41) "T3497012 @ AHOSTBRHDDSB @ EICM_BORA @ BPHS @ Bamz"
  [4] = > string (41) "T3497012 @ BHOSTBRHDDSB @ EICM_BORA @ BPHS @ Bamz"
  [5] = > string (41) "T3497012 @ CHOSTBRHDDSB @ EICM_BORA @ BPHS @ Bamz"
  [6] = > string (41) "T3497012 @ AHOSTBRHDDSB @ EICM_BORB @ BPHS @ Aama"
  [7] = > string (41) "T3497012 @ AHOSTBRHDDSB @ EICM_BORC @ APHS @ bed"
  }

See it working

    
21.01.2018 / 22:45