Tengo este tipo de estructura de datos

$scores = [
  'user_a' => [75, 67, 80, 90, 20, 80],
  'user_b' => [65, 70, 80, 90, 20, 80],
  'user_c' => [56, 70, 75, 80, 50, 70],
  'user_d' => [40, 50, 89, 56, 45, 78],
  'user_e' => [60, 80, 90, 78, 80, 76],
];

Quiero obtener el número máximo de user_a a user_e cada uno verticalmente. Lo que espero es algo como esto:

$max = [75, 80, 90, 90, 80];

Intenté esto, pero el número se toma horizontalmente por clave.

$max = [];
foreach ($scores as $score) {
  array_push($max, max($score));
}

var_dump($max); // [90, 90, 80, 89, 90];

¿Cuál es la forma correcta de lograr esto?

php
0
Tamma 7 jul. 2021 a las 21:09

3 respuestas

La mejor respuesta

Solución sofisticada pero aún así:

$scores = [
  'user_a' => [75, 67, 80, 90, 20, 80],
  'user_b' => [65, 70, 80, 90, 20, 80],
  'user_c' => [56, 70, 75, 80, 50, 70],
  'user_d' => [40, 50, 89, 56, 45, 78],
  'user_e' => [60, 80, 90, 78, 80, 76],
];

$max =  array_map(
    'max', 
    array_map(null, ...array_values($scores))
);
print_r($max);

Fiddle.

1
u_mulder 7 jul. 2021 a las 18:15

He aquí una forma sencilla. Simplemente extraiga cada columna y max:

$i = 0;
while($col = array_column($scores, $i)) { $max[] = max($col); $i++; }

U otras variaciones:

for($i=0; $col=array_column($scores, $i); $i++, $max[]=max($col));

Puede hacer varias cosas en esos bucles, solo agregue $min[] = min($col);, etc.

Para extraer las columnas para su uso posterior:

$i = 0;
while($col = array_column($scores, $i)) { $vals[] = $col; $i++; }

Luego úsalos como quieras:

foreach($vals as $col) { 
    $min[] = min($col);
    $max[] = max($col);
}
//or
$max = array_map('max', $vals);

O una función para obtener las columnas y realizar una función. Simplemente pase min, max o lo que sea que acepte una matriz:

function get_cols($array, $func) {
    for($i=0; $col=array_column($array, $i); $i++) {
        $result[] = $func($col);
    }
    return $result;
}

$max = get_cols($scores, 'max');
1
AbraCadaver 7 jul. 2021 a las 19:55

Esta es mi solución si necesita más control sobre los valores mapeados.

<?php

$scores = [
  'user_a' => [75, 67, 80, 90, 20, 80],
  'user_b' => [65, 70, 80, 90, 20, 80],
  'user_c' => [56, 70, 75, 80, 50, 70],
  'user_d' => [40, 50, 89, 56, 45, 78],
  'user_e' => [60, 80, 90, 78, 80, 76],
];

// Get vertical score lines
$verticalScores = array_reduce($scores, function($carry, $score) {
    foreach($score as $key => $value) {
        $carry[$key][] = $value;    
    }
    return $carry;
}, []);


// Get max score per vertical line
$maxScores = array_map('max', $verticalScores);


var_dump($maxScores); //75, 80, 90, 90, 80, 80
2
Robert Wagner 7 jul. 2021 a las 18:32