Sort object list with PHP

Asked

Viewed 181 times

0

Good afternoon, I’m doing an activity to get a little more handy with PHP, and I decided to take the data from a cvs file, and show them on the screen... until then ok, I got it. But I had the idea after trying to sort this data through a calculation that I do in the code itself, using data from the CSV file, but I am not able to order them, I will leave the following code.

<?php

    $delimitador = ',';
    $cerca = '"';

    // Abrir arquivo para leitura
    $f1 = fopen('$ cat dataset1.csv', 'r');
    $f2 = fopen('$ cat dataset2.csv', 'r');

    if ($f1 && $f2) { 

        // Ler cabecalho do arquivo
        $cabecalho1 = fgetcsv($f1, 0, $delimitador, $cerca);
        $cabecalho2 = fgetcsv($f2, 0, $delimitador, $cerca);

        echo "<ol>";
        // Enquanto nao terminar o arquivo
        while (!feof($f1) && !feof($f2)) { 

            // Ler uma linha do arquivo
            $linha1 = fgetcsv($f1, 0, $delimitador, $cerca);
            if (!$linha1) {
                continue;
            }
            $linha2 = fgetcsv($f2, 0, $delimitador, $cerca);
            if (!$linha2) {
                continue;
            }

            // Montar registro com valores indexados pelo cabecalho
            $registro1 = array_combine($cabecalho1, $linha1);
            $registro2 = array_combine($cabecalho2, $linha2);

            // Verifica quais dos dinossauros são bípedes
            if($registro2['STANCE'] == 'bipedal'){
                // Faz o calculo da velocidade de cada um dos dinossauros bípedes
                $g = 9.8;
                $velocidade = (($registro2['STRIDE_LENGTH'] / $registro1['LEG_LENGTH']) - 1) * SQRT($registro1['LEG_LENGTH']) * $g;

                // Obtendo o nome
                echo "<li>".$registro2['NAME'].PHP_EOL." -> ".$velocidade." m/s²</li>";
            }
        }
        echo "</ol>";
        fclose($f2);
    }
?>

How I could dynamically make the ordered list ?

EDIT1: What I want to do, being direct, is sort the values of the file. csv so that they are in order from the highest speed to the lowest, which would be done within the if($registro2['STANCE'] == 'bipedal'). I’m beginning to learn the language and I have no idea how to do this ordering.

EDIT 2: I will leave below exact as I am currently doing for you to try to reproduce.

index php.

<?php

    $delimitador = ',';
    $cerca = '"';

    // Abrir arquivo para leitura
    $f1 = fopen('$ cat dataset1.csv', 'r');
    $f2 = fopen('$ cat dataset2.csv', 'r');

    if ($f1 && $f2) { 

        // Ler cabecalho do arquivo
        $cabecalho1 = fgetcsv($f1, 0, $delimitador, $cerca);
        $cabecalho2 = fgetcsv($f2, 0, $delimitador, $cerca);

        echo "<ol>";
        // Enquanto nao terminar o arquivo
        while (!feof($f1) && !feof($f2)) { 

            // Ler uma linha do arquivo
            $linha1 = fgetcsv($f1, 0, $delimitador, $cerca);
            if (!$linha1) {
                continue;
            }
            $linha2 = fgetcsv($f2, 0, $delimitador, $cerca);
            if (!$linha2) {
                continue;
            }

            // Montar registro com valores indexados pelo cabecalho
            $registro1 = array_combine($cabecalho1, $linha1);
            $registro2 = array_combine($cabecalho2, $linha2);

            // Verifica quais dos dinossauros são bípedes
            if($registro2['STANCE'] == 'bipedal'){
                // Faz o calculo da velocidade de cada um dos dinossauros bípedes
                $g = 9.8;
                $velocidade = (($registro2['STRIDE_LENGTH'] / $registro1['LEG_LENGTH']) - 1) * SQRT($registro1['LEG_LENGTH']) * $g;

                $array = array("nome" => $registro2['NAME'], "velocidade" => $velocidade);

            }
        }
        echo "</ol>";
        fclose($f2);
    }
?>

$ cat dataset1.csv

NAME,LEG_LENGTH,DIET
Hadrosaurus,1.2,herbivore
Struthiomimus,0.92,omnivore
Velociraptor,1.0,carnivore
Triceratops,0.87,herbivore
Euoplocephalus,1.6,herbivore
Stegosaurus,1.40,herbivore
Tyrannosaurus Rex,2.5,carnivore

$ cat dataset2.csv

NAME,STRIDE_LENGTH,STANCE
Euoplocephalus,1.87,quadrupedal
Stegosaurus,1.90,quadrupedal
Tyrannosaurus Rex,5.76,bipedal
Hadrosaurus,1.4,bipedal
Deinonychus,1.21,bipedal
Struthiomimus,1.34,bipedal
Velociraptor,2.72,bipedal
  • Important you [Dit] your post and explain in detail the problem by describing what you tried and where is the current difficulty. Requests for complete refactoring or ready code, tutorials and/or things involving more than one subject in the same post usually do not fit the site scope. Links to better understand how Sopt works: [Tour], [Ask], Manual on how NOT to ask questions and [Help]. If you have any questions about specific details, reducing the code to a [MCVE] can help a lot.

  • Thanks for the review, @Bacco , I just edited the post, could give me a help ?

  • Try making a [mcve], only with the part that is struggling. With this code everyone would first have to understand it and then see how to do what they want, and still a huge tutorial explaining the modified code, which does not work well in the scope of the site. With a [mcve] and an example of how you have the data and how it should look, it gives the community a better understanding to perhaps make a response possible.

  • Another thing, to sort in the place you said, do if (that is, before you have read all the records), you would have to look for the right position at all times, which is not a simple thing to do, involves several parts, perhaps a binary search or qq other kind of indexing (find the right place to put the element, maybe using a linked list), complicated to simple question and simple answer

  • so if I set up an array inside if and try to sort it later it would be better? @Bacco

  • Not necessarily. If the CSV is long, or if it runs many processes in parallel, it will have memory problem. If it’s a short CSV, the array might be a good one. If you could do a [mcve] with an example data set it would help make the post viable.

  • @Bacco, can you reproduce the way I left it in the question? I couldn’t make a minimal and virifiable example to leave there...

  • I reopened, but honestly without the [mcve] it gets complicated because you have to analyze your code and try to understand everything. If you took out all the parts not important, and only left the part that has doubt (the one that processes the array), it would make it easier. The less code and noise, the better.

  • I apologize for the way I left @Bacco, I’m a beginner, but I believe the code is not that big. If you can give me a hand in this thank you. In the next questions I will try to put a minimal example, thank you for the criticism

  • Thanks @Augustovasques, thanks for your cooperation ;)

Show 5 more comments

1 answer

1

To sort what you want, sort the values of the file .csv in order to be in order from the highest speed to the lowest (descending order), I had to initially create two functions.

1 - velocity($bipedal) which calculates the speed of a biped with respect to step size, leg size and gravity, as shown in the example.

2 - compare_bibedals($a, $b) which compares the velocity of two bipeds, and only bipeds, returning a comparative integer in descending order, i.e.:

$a == $b => 0

$a < $b => 1

$a > $b => -1

I also used the function usort which sorts an array by values using a user-defined comparison function, in this case compare_bibedals.

I changed the logical layout of the code. Initially the code focuses only on extracting data from .csv, the files were read independently in order to minimize the use of resources. Then the activity is focused on working, separating and sorting the obtained data and then finishing by building a table of HTML.

<?php

    //Calcula a velocidade de um dinossauro bípede
    function velocity($bipedal){
        return (($bipedal['STRIDE_LENGTH'] / $bipedal['LEG_LENGTH']) - 1) * SQRT($bipedal['LEG_LENGTH']) * 9.8;
    }

    //Compara as velocidades de dois dinossauros de forma descendente
    function compare_bibedals($a, $b)
    {   
        // Se as velocidades forem iguais retorna 0
        // Se a velocidade $a < $b retorna  1
        // Se a velocidade $a < $b retorna -1
        if ($a['VELOCITY'] == $b['VELOCITY']) return 0;
        return ($a['VELOCITY'] < $b['VELOCITY']) ? 1 : -1;
    }

    $delimitador = ',';
    $registro = []; // Registro geral onde todos os dados serão mesclados.
    $registro1 = []; // Registro qual será armazenado dataset1
    $registro2 = []; // Registro qual será armazenado dataset2

    // Trabalha individualmente o arquivos dataset1.csv
    $f1 = fopen('dataset1.csv', 'r');
    if ($f1){
       $cabecalho1 = fgetcsv($f1, 0, $delimitador);
        while (!feof($f1)){
            $linha1 = fgetcsv($f1, 0, $delimitador);
            if (!$linha1) {
                continue;
            }
            $registro1[] = array_combine($cabecalho1, $linha1);
        }

    }
    // Terminada as operações com os arquivos eles são fechados para poupar recursos do sistema.
    fclose($f1);

    // Trabalha individualmente o arquivos dataset2.csv
    $f2 = fopen('dataset2.csv', 'r');
    if ($f2){
       $cabecalho2 = fgetcsv($f2, 0, $delimitador);
        while (!feof($f2)){
          $linha2 = fgetcsv($f2, 0, $delimitador);
            if (!$linha2) {
                continue;
            }
            $registro2[] = array_combine($cabecalho2, $linha2);
        }

    }
    // Terminada as operações com os arquivos eles são fechados para poupar recursos do sistema.
    fclose($f2);

    //Mescla os dados obtidos em $registro1 e $registro1 pelo nome
    foreach($registro1 as $dino_info1){
      foreach($registro2 as $dino_info2){
        //Compara ambos registros pelo nome
        if ($dino_info1['NAME'] == $dino_info2['NAME']){
          //Somente os bipedes
          if ($dino_info2['STANCE']!='bipedal') continue 2;
          //Mescla os dois registros
          $bibedal = array_merge((array) $dino_info1, (array) $dino_info2);
          //Adiciona velocidade
          $bibedal['VELOCITY'] = velocity($bibedal);
          //Coloca o resultado no registro geral
          $registro[] = $bibedal;
          continue 2;
        }
      }
    }
    //Ordena o registro geral usando a função compare_bibedals
    usort($registro, "compare_bibedals"); 

    //Imprime uma lista comum com os dados dos dinossauro já ordenada pelo PHP
    echo "<ul>";
    foreach($registro as $dino){
      echo "<li>";
      echo "<span>Nome: " . $dino['NAME'] . "</span></br>";
      echo "<span>Dieta: " . $dino['DIET'] . "</span></br>";
      echo "<span>Comprimento do passo: " . $dino['STRIDE_LENGTH'] . "</span></br>";
      echo "<span>Posição: " . $dino['STANCE'] . "</span></br>";
      echo "<span>Comprimento da perna: " . $dino['LEG_LENGTH'] . "</span></br>";
      echo "<span>Velocidade: " . $dino['VELOCITY'] . "</span></br>";
      echo "</li>";
    }        
    echo "</ul>";       

?>

The result of which is :

<ul>
  <li><span>Nome: Tyrannosaurus Rex</span></br><span>Dieta: carnivore</span></br><span>Comprimento do passo: 5.76</span></br><span>Posição: bipedal</span></br><span>Comprimento da perna:2.5</span></br><span>Velocidade: 20.205689337412</span></br>
  </li>
  <li><span>Nome: Velociraptor</span></br><span>Dieta: carnivore</span></br><span>Comprimento do passo: 2.72</span></br><span>Posição: bipedal</span></br><span>Comprimento da perna: 1.0</span></br><span>Velocidade: 16.856</span></br>
  </li>
  <li><span>Nome: Struthiomimus</span></br><span>Dieta: omnivore</span></br><span>Comprimento do passo: 1.34</span></br><span>Posição: bipedal</span></br><span>Comprimento da perna: 0.92</span></br><span>Velocidade: 4.2912266412946</span></br>
  </li>
  <li><span>Nome: Hadrosaurus</span></br><span>Dieta: herbivore</span></br><span>Comprimento do passo: 1.4</span></br><span>Posição: bipedal</span></br><span>Comprimento da perna: 1.2</span></br><span>Velocidade: 1.7892270211835</span></br>
  </li>
</ul>

Link working on Repl.it

Browser other questions tagged

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