Group by matches in a PHP array

2

I have a multidimensional array with indexes, in which I keep the data, about a user and their stops, this I show for days. I am interested in the days that have the same stops are grouped.

The array I get from two SQL queries in this way:

$resultado = listado1($alumnos,$etapas,$clases,$grupos,$ano,$filtroUsuarios,$filtroEtapas,$filtroClase,$filtroGrupo);//Primera consulta
$arrParadasPorDia = Array();
//En el primer for agrupo las paradas que tiene un dia
for($i=0;$i<count($resultado);$i++){//Recojo los valores de la primera consulta y los voy guardando en un nuevo array (Para unirlo con la otra consulta)
    $tmp = Array(); 
    $tmp["ANO"] = $resultado[$i]["ANO"];//AÑO
    $tmp["NOMBRE"] = $resultado[$i]["NOMBRE"];//NOMBRE USUARIO
    $tmp["CODUSU"] = $resultado[$i]["CODUSU"];//CODIGO USUARIO
    $tmp["ENCARGADO"] = $resultado[$i]["ENCARGADO"];//ENCARGADO DEL USUARIO
    $tmp["TLFNO"] = $resultado[$i]["TLFNO"];//TELEFONO DEL USUARIO
    $tmp["DIASEMANA"] = $resultado[$i]["DIASEMANA"];//DIA DE LA SEMANA
    $paradas = Array(); //Creo un nuevo array para guardar los valores de la segunda consulta
    $resultado2 = listado2($resultado[$i]["TSRVDSE"],$resultado[$i]["USCOD"]); //Ejecuto la segunda consulta que tiene como filtros valores de la primera de ellas
    for($j=0;$j<count($resultado2);$j++){   //Recorro la segunda consulta
        $tmp2 = Array();
        $tmp2["HORA"] = $resultado2[$j]["HORA"];//HORA
        $tmp2["PARADA"] = $resultado2[$j]["PARADA"];//PARADA
        $tmp2["CALLE"] = $resultado2[$j]["CALLE"];//CALLE
        array_push($paradas,$tmp2);
    }
    $tmp["PARADAS"] = $paradas;//AÑADO EL ARRAY DE LA SEGUNDA CONSULTA A UN "INDICE" DEL PRIMER ARRAY
    array_push($arrParadasPorDia,$tmp);//GUARDO EL RESULTADO EL EN ARRAY PRIMARIO   
}

Once this is done I have the data saved correctly, I can see the results in this way:

foreach($arrParadasPorDia as $resultado){
    echo "AÑO ".$resultado["ANO"]."<br/>";
    echo "NOMBRE ".$resultado["NOMBRE"]."<br/>";
    echo "USUARIO ".$resultado["CODUSU"]."<br/>";
    echo "TUTOR ".$resultado["ENCARGADO"]."<br/>";
    echo "TLFNO ".$resultado["TLFNO"]."<br/>";
    echo "DIA SEMANA ".$resultado["DIASEMANA"]."<br/>";
    $i = 0;     
    foreach($resultado["PARADAS"] as $paradas){
        $i++;
        echo "PARADA".$i.": ";
        echo "DIRECION ".$paradas["TSRVDIR"]."<br/>";
        echo "HORA ".$paradas["HORA"]."<br/>";
        echo "PARADA ".$paradas["PARADA"]."<br/>";
        echo "CALLE".$paradas["CALLE"]."<br/>";
    }
    echo "<hr/>";
}

The results I show are something like this:

AÑO 2016
NOMBRE ANDONI ALDA
USUARIO 000001
ENCARGADO ANDONI ALDA
TLFNO 666000666
DIA SEMANA 1
PARADA1:
HORA 855
PARADA 1
CALLE C/MAYOR

PARADA2:
HORA 1040
PARADA 1
CALLE C/MENOR

AÑO 2016
NOMBRE ANDONI ALDA
USUARIO 000001
ENCARGADO ANDONI ALDA
TLFNO 666000666
DIA SEMANA 2
PARADA1:
HORA 855
PARADA 1
CALLE C/MAYOR

PARADA2:
HORA 1040
PARADA 1
CALLE C/MENOR

AÑO 2016
NOMBRE ANDONI ALDA
USUARIO 000001
ENCARGADO ANDONI ALDA
TLFNO 666000666
DIA SEMANA 3
PARADA1:
HORA 855
PARADA 1
CALLE C/MAYOR

PARADA2:
HORA 1040
PARADA 1
CALLE C/MENOR

AÑO 2016
NOMBRE ANDONI ALDA
USUARIO 000001
ENCARGADO ANDONI ALDA
TLFNO 666000666
DIA SEMANA 4
PARADA1:
HORA 855
PARADA 1
CALLE C/MAYOR

PARADA2:
HORA 1040
PARADA 1
CALLE C/MENOR

AÑO 2016
NOMBRE ANDONI ALDA
USUARIO 000001
ENCARGADO ANDONI ALDA
TLFNO 666000666
DIA SEMANA 5
PARADA1:
HORA 855
PARADA 1
CALLE C/PUERTOURRACO

PARADA2:
HORA 1040
PARADA 1
CALLE Avenida de la playa

As you can see, the days 1, 2, 3 and 4 have the same stops at the same time and on the 5th you have the stops at the same time but at a different place.

I would like the data to be shown in the following way:

AÑO 2016
NOMBRE ANDONI ALDA
USUARIO 000001
ENCARGADO ANDONI ALDA
TLFNO 666000666
DIA SEMANA 1,2,3,4
PARADA1:
HORA 855
PARADA 1
CALLE C/MAYOR

PARADA2:
HORA 1040
PARADA 1
CALLE C/MENOR


AÑO 2016
NOMBRE ANDONI ALDA
USUARIO 000001
ENCARGADO ANDONI ALDA
TLFNO 666000666
DIA SEMANA 5
PARADA1:
HORA 855
PARADA 1
CALLE C/PUERTOURRACO

PARADA2:
HORA 1040
PARADA 1
CALLE Avenida de la playa

And not only show them, if it is possible to save them in an array.

I've managed to group like this:

$arrFinal = Array();
$primera = true;
$dias = "";
for($i=0;$i<count($arrParadasPorDia);$i++){
    if($i == 0){//Si es la primera vez que pasa se almacenan los datos en un array temporal         
        $tmp = Array();
        $tmp["ANO"] = $arrParadasPorDia[$i]["ANO"];
        $tmp["NOMBRE"] = $arrParadasPorDia[$i]["NOMBRE"];
        $tmp["CODUSU"] = $arrParadasPorDia[$i]["CODUSU"];
        $tmp["ENCARGADO"] = $arrParadasPorDia[$i]["ENCARGADO"];
        $tmp["TLFNO"] = $arrParadasPorDia[$i]["TLFNO"];
        $dias = $arrParadasPorDia[$i]["DIASEMANA"]; //Variable que recojera los dias iguales.
        $tmp["PARADAS"] = $arrParadasPorDia[$i]["PARADAS"];
    }else{
    if($arrParadasPorDia[$i]["PARADAS"] == $arrParadasPorDia[$i-1]["PARADAS"]){//Si la las paradas son iguales a las del dia anterior se almacena el dia en la variable dias
        $dias = $dias.", ".$arrParadasPorDia[$i]["DIASEMANA"];
    }else{//Si son distintos
        $tmp["DIAS"] = $dias;//Guardo la variable dias en el array temporal
        array_push($arrFinal,$tmp);//Añado el array temporal al definitivo
        $tmp = Array();//Vacio el array y le añado los datos del dia que es distinto
        $tmp["ANO"] = $arrParadasPorDia[$i]["ANO"];
        $tmp["NOMBRE"] = $arrParadasPorDia[$i]["NOMBRE"];
        $tmp["CODUSU"] = $arrParadasPorDia[$i]["CODUSU"];
        $tmp["ENCARGADO"] = $arrParadasPorDia[$i]["ENCARGADO"];
        $tmp["TLFNO"] = $arrParadasPorDia[$i]["TLFNO"];
        $dias = $arrParadasPorDia[$i]["DIASEMANA"];
        $tmp["PARADAS"] = $arrParadasPorDia[$i]["PARADAS"];
        }
    }
}
$tmp["DIAS"] = $dias;//El ultimo dia no se guarda en el array porque sale del for antes de guardar por lo que hay que hacer esto.
array_push($arrFinal,$tmp);

This could be a solution but it has a problem, for example, if day 1, 2 and 4 are the same and 3 and 5 are different, it should show 3 results, one for day 1, 2 and 4, another for day 3 and another for 5, but with this method I show 4 results. One for day 1 and 2 another for day 3 another for day 4 and a last day for day 5, so this solution is valid, but it is not what I'm looking for.

By request of @OscarGarcia and @Mariano I leave the data resulting from var_export($arrParadasPorDia) to work with them:

array ( 0 => array 
    ( 'ANO' => 2016,    
        'NOMBRE' => 'ANDONI ALDA', 
        'USCOD' => '000001',    
        'ENCARGADO' => 'ANDONI ALDA',
        'USRTELEFONO' => 685358487,      
        'DIASEMANA' => 1,
        'PARADAS' =>
        array ( 0 => array 
            ('HORA' => 855,
            'PARADA' => 1,
            'CALLE' => 'C/MAYOR',
            ),
            1 => array 
            ( 'HORA' => 1040,
            'PARADA' => 1,
            'CALLE' => 'C/MENOR',
            ),
        ),
    ), 
     1 => array 
        ( 'ANO' => 2016,    
        'NOMBRE' => 'ANDONI ALDA', 
        'USCOD' => '000001',    
        'ENCARGADO' => 'ANDONI ALDA',
        'USRTELEFONO' => 685358487,      
        'DIASEMANA' => 2,
        'PARADAS' =>
        array ( 0 => array 
            ('HORA' => 855,
            'PARADA' => 1,
            'CALLE' => 'C/MAYOR',
            ),
            1 => array 
            ( 'HORA' => 1040,
            'PARADA' => 1,
            'CALLE' => 'C/MENOR',
            ),
        ),
    ),
    2 => array 
        ( 'ANO' => 2016,    
        'NOMBRE' => 'ANDONI ALDA', 
        'USCOD' => '000001',    
        'ENCARGADO' => 'ANDONI ALDA',
        'USRTELEFONO' => 685358487,      
        'DIASEMANA' => 3,
        'PARADAS' =>
        array ( 0 => array 
            ('HORA' => 855,
            'PARADA' => 1,
            'CALLE' => 'C/MAYOR',
            ),
            1 => array 
            ( 'HORA' => 1040,
            'PARADA' => 1,
            'CALLE' => 'C/MENOR',
            ),
        ),
    ),
    3 => array 
        ( 'ANO' => 2016,    
        'NOMBRE' => 'ANDONI ALDA', 
        'USCOD' => '000001',    
        'ENCARGADO' => 'ANDONI ALDA',
        'USRTELEFONO' => 685358487,      
        'DIASEMANA' => 4,
        'PARADAS' =>
        array ( 0 => array 
            ('HORA' => 855,
            'PARADA' => 1,
            'CALLE' => 'C/MAYOR',
            ),
            1 => array 
            ( 'HORA' => 1040,
            'PARADA' => 1,
            'CALLE' => 'C/MENOR',
            ),
        ),
    ), 
    4 => array 
        ( 'ANO' => 2016,    
        'NOMBRE' => 'ANDONI ALDA', 
        'USCOD' => '000001',    
        'ENCARGADO' => 'ANDONI ALDA',
        'USRTELEFONO' => 685358487,      
        'DIASEMANA' => 5,
        'PARADAS' =>
        array ( 0 => array 
            ('HORA' => 855,
            'PARADA' => 1,
            'CALLE' => 'CALLE C/PUERTOURRACO',
            ),
            1 => array 
            ( 'HORA' => 1040,
            'PARADA' => 1,
            'CALLE' => 'Avenida de la playa',
            ),
        ),
    ),
)
    
asked by Lombarda Arda 17.05.2017 в 10:29
source

1 answer

2

I have developed this loop that performs the function you want (below I explain how it works):

<?php
header('Content-Type: text/plain; charset=utf-8');
$datos = array (
 0 => array
    ( 'ANO' => 2016,
    'NOMBRE' => 'ANDONI ALDA',
    'USCOD' => '000001',
    'ENCARGADO' => 'ANDONI ALDA',
    'USRTELEFONO' => 685358487,
    'DIASEMANA' => 1,
    'PARADAS' =>
    array ( 0 => array
        ('HORA' => 855,
        'PARADA' => 1,
        'CALLE' => 'C/MAYOR',
        ),
        1 => array
        ( 'HORA' => 1040,
        'PARADA' => 1,
        'CALLE' => 'C/MENOR',
        ),
    ),
),
 1 => array
    ( 'ANO' => 2016,
    'NOMBRE' => 'ANDONI ALDA',
    'USCOD' => '000001',
    'ENCARGADO' => 'ANDONI ALDA',
    'USRTELEFONO' => 685358487,
    'DIASEMANA' => 2,
    'PARADAS' =>
    array ( 0 => array
        ('HORA' => 855,
        'PARADA' => 1,
        'CALLE' => 'C/MAYOR',
        ),
        1 => array
        ( 'HORA' => 1040,
        'PARADA' => 1,
        'CALLE' => 'C/MENOR',
        ),
    ),
),

2 => array
    ( 'ANO' => 2016,
    'NOMBRE' => 'ANDONI ALDA',
    'USCOD' => '000001',
    'ENCARGADO' => 'ANDONI ALDA',
    'USRTELEFONO' => 685358487,
    'DIASEMANA' => 3,
    'PARADAS' =>
    array ( 0 => array
        ('HORA' => 855,
        'PARADA' => 1,
        'CALLE' => 'C/MAYOR',
        ),
        1 => array
        ( 'HORA' => 1040,
        'PARADA' => 1,
        'CALLE' => 'C/MENOR',
        ),
    ),
),
3 => array
    ( 'ANO' => 2016,
    'NOMBRE' => 'ANDONI ALDA',
    'USCOD' => '000001',
    'ENCARGADO' => 'ANDONI ALDA',
    'USRTELEFONO' => 685358487,
    'DIASEMANA' => 4,
    'PARADAS' =>
    array ( 0 => array
        ('HORA' => 855,
        'PARADA' => 1,
        'CALLE' => 'C/MAYOR',
        ),
        1 => array
        ( 'HORA' => 1040,
        'PARADA' => 1,
        'CALLE' => 'C/MENOR',
        ),
    ),
),
4 => array
    ( 'ANO' => 2016,
    'NOMBRE' => 'ANDONI ALDA',
    'USCOD' => '000001',
    'ENCARGADO' => 'ANDONI ALDA',
    'USRTELEFONO' => 685358487,
    'DIASEMANA' => 5,
    'PARADAS' =>
    array ( 0 => array
        ('HORA' => 855,
        'PARADA' => 1,
        'CALLE' => 'CALLE C/PUERTOURRACO',
        ),
        1 => array
        ( 'HORA' => 1040,
        'PARADA' => 1,
        'CALLE' => 'Avenida de la playa',
        ),
    ),
));
$resultado = [];
foreach($datos as $dato) {
    if (!isset($resultado[$dato['USCOD']])) {
        $resultado[$dato['USCOD']] = $dato;
        unset(
          $resultado[$dato['USCOD']]['DIASEMANA'],
          $resultado[$dato['USCOD']]['PARADAS']
        );
        $resultado[$dato['USCOD']]['RUTAS'] = [];
    }
    $clave = [];
    foreach($dato['PARADAS'] as $parada) {
        array_push($clave, $parada['HORA'], $parada['CALLE']);
    }
    $clave = implode(':', $clave);
    if (!isset($resultado[$dato['USCOD']]['RUTAS'][$clave])) {
        $resultado[$dato['USCOD']]['RUTAS'][$clave] = [
            'DIAS' => [],
            'PARADAS' => $dato['PARADAS'],
        ];
    }
    array_push($resultado[$dato['USCOD']]['RUTAS'][$clave]['DIAS'], $dato['DIASEMANA']);
}

foreach($resultado as $clave => $valor) {
  $resultado[$clave]['RUTAS'] = array_values($valor['RUTAS']);
}
$resultado = array_values($resultado);
echo json_encode($resultado, JSON_PRETTY_PRINT);

The result shown is:

[
  {
    "ANO": 2016,
    "NOMBRE": "ANDONI ALDA",
    "USCOD": "000001",
    "ENCARGADO": "ANDONI ALDA",
    "USRTELEFONO": 685358487,
    "RUTAS": [
      {
        "DIAS": [
          1,
          2,
          3,
          4
        ],
        "PARADAS": [
          {
            "HORA": 855,
            "PARADA": 1,
            "CALLE": "C\/MAYOR"
          },
          {
            "HORA": 1040,
            "PARADA": 1,
            "CALLE": "C\/MENOR"
          }
        ]
      },
      {
        "DIAS": [
          5
        ],
        "PARADAS": [
          {
            "HORA": 855,
            "PARADA": 1,
            "CALLE": "CALLE C\/PUERTOURRACO"
          },
          {
            "HORA": 1040,
            "PARADA": 1,
            "CALLE": "Avenida de la playa"
          }
        ]
      }
    ]
  }
]

How it works

Main loop in which we check if a user exists (looking for its primary key, used as an index in the matrix, adding the data to it as needed:

$resultado = [];
foreach($datos as $dato) {
    if (!isset($resultado[$dato['USCOD']])) {
        $resultado[$dato['USCOD']] = $dato;
        unset(
          $resultado[$dato['USCOD']]['DIASEMANA'],
          $resultado[$dato['USCOD']]['PARADAS']
        );
        $resultado[$dato['USCOD']]['RUTAS'] = [];
    }

In this loop we generate an index for the route matrix that will be unique for each route (sequential concatenation of time / direction):

    $clave = [];
    foreach($dato['PARADAS'] as $parada) {
        array_push($clave, $parada['HORA'], $parada['CALLE']);
    }
    $clave = implode(':', $clave);

If the route does not exist, we generate the initial data:

    if (!isset($resultado[$dato['USCOD']]['RUTAS'][$clave])) {
        $resultado[$dato['USCOD']]['RUTAS'][$clave] = [
            'DIAS' => [],
            'PARADAS' => $dato['PARADAS'],
        ];
    }

We add the day to the route:

    array_push($resultado[$dato['USCOD']]['RUTAS'][$clave]['DIAS'], $dato['DIASEMANA']);

We finished the main loop:

}

We clean the indexes that we have used to manage the repetition of routes of a user and the user himself:

foreach($resultado as $clave => $valor) {
  $resultado[$clave]['RUTAS'] = array_values($valor['RUTAS']);
}
$resultado = array_values($resultado);
    
answered by 17.05.2017 / 16:02
source