Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

ronaldoribe

Subgrupo in array foreach

Recommended Posts

Eu tenho a seguinte situação abaixo, da forma como está eu consigo obter o número total de animais, porém eu gostaria de obter alem do total, obter tambem pelo genero, ou seja, o numero de animais por categoria e por sexo. Como posso trabalhar com dois grupos nesse código array? Valeu galera, grande abraço

Hamster Machos 15
Hamster femeas 6

$animal = Array (
[0] => Array (
[0] => Hamster
[1] => Male
[2] => 10)

[1] => Array (
[0] => Hamster
[1] => Male
[2] => 5)

[2] => Array (
[0] => Hamster
[1] => Female
[2] => 6)


foreach ($animal as $line)
{
$group[$line[0]][] = $line[2];}


foreach ($group as $x => $y)
{
$total = '';
$total = array_sum($y);

echo $x." = ".$total;}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fiz uma brincadeirinha aqui... talvez lhe seja útil ou lhe dê alguma ideia:

 

$animais =
  [[
    "Hamster",
    "Male",
    "10"
  ],[
    "Hamster",
    "Male",
    "5"
  ],[
    "Hamster",
    "Female",
    "6"
  ]];

  
/*
 * Retorna o número de animais por determinado critário
 *
 */
function conta_animais_criterio($especie = null, $genero = null, $categoria = null)
{
    global $animais;
    
    $resultado = 0;
    
    foreach ($animais as $animal)
    {
        $animal = array_combine(
                    ['especie', 'genero', 'categoria'],
                    $animal);
        
        if (
          (is_null($especie) or ($animal['especie'] == $especie)) and
          (is_null($genero) or ($animal['genero'] == $genero)) and
          (is_null($categoria) or ($animal['categoria'] == $categoria))
        ) {
            $resultado += 1;
        }
        
    }
    
    return $resultado;
}

// Todos
$con0 = conta_animais_criterio();

// Todos os 'Hamster'
$con1 = conta_animais_criterio("Hamster");

// Todos os 'Hamster' e 'Male'
$con2 = conta_animais_criterio("Hamster", "Male");

// Todos os 'Female'
$con3 = conta_animais_criterio(null, "Female");

// Todos os 'Male' com categoria '6'
$con4 = conta_animais_criterio(null, "Male", "6");



var_dump($con0, $con1, $con2, $con3, $con4);

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sua idéia foi muito boa Mangakah, mas por falta de explicação dei a entender que os numeros 10, 5 e 6 fossem categorias, na verdade esses são os numero de animais, o resultado seria

 

Animal machos femeas total

Hamster 10 5 15

Hamster 0 6 6

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ainda não mangakah, eu consigo obter somente os totais. No código que tenho

 

foreach ($animal as $line)
{
$group[$line[0]][] = $line[2];} se eu trocar o $line[0] por $line[1], eu obtenho o numero total de femeas e machos, mas

é ignorado a especie do animal, a impressão que tenho é que falta algo como

 

$group[$line[especie][$line[genero]]][] = $line[2]; já tentei isso, mas ainda não funcionou

Compartilhar este post


Link para o post
Compartilhar em outros sites

Humm... agora acho que entendi o que você quer.

 

Eu respondi um tópico agora a pouco e acho que minha resposta vale para o seu caso...

 

http://forum.imasters.com.br/topic/495941-problema-com-array/

 

Tudo que você precisa fazer é substituir os nomes das chaves do array: 'dia' por 0, 'operador' por 1 e 'total' por 2. Assim:

 

    $novo_arr[$arr[0]][$arr[1]] =
      isset($novo_arr[$arr[0]][$arr[1]]) ?
        $novo_arr[$arr[0]][$arr[1]] + $arr[2] :
        $arr[2];

Compartilhar este post


Link para o post
Compartilhar em outros sites

Amigo no caso um exemplo de uma pequena class que podem lhe ajudar.

 

<?php
class FilterSexGroup{
    public $count;//TOTAL DE ANIMAIS DOS GRUPOS.
    public $group;//ARRAY FORMADO DE ACORDO COM O FILTRO.

    public function Filter($arr,$filter)
    {
        
        $this->group = array();
        $this->count = 0;

        foreach($arr as $item){
            
            if(array_search($filter,$item)){
                $this->group[] = $item;
                $this->count += $item[2];
            }

        }

    }

}
?>

 


exemplo de uso:

 

 

$animal = array(array('Hamster','Male',10),    array('Hamster','Male',5),    array('Hamster','Female',6));
$filter = new FilterSexGroup;
$filter->Filter($animal,'Female');
print_r($filter->group);
echo 'TOTAL: '.$filter->count;

retorno:

 

Array
(
    [0] => Array
        (
            [0] => Hamster
            [1] => Female
            [2] => 6
        )

)
TOTAL: 6

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu estava procurando a frase que o Simon Baker disse em um eipisódio de The Mentalist mas parafrasear a a Navalha de Ockham, precursora do bom e velho KISS (Keep it simple, stupid) também vale.

Por quê você simplesmente não criar uma função que automatize a filtragem de um array baseado na existência/ausência de um determinado valor?

Olha só:

function filter( $needle, $haystack )  {
 
    return array_filter(
 
        $haystack,
 
        function( $current ) use( $needle ) {
 
            return ( array_search( $needle, $current ) !== FALSE );
        }
    );
}
 
$animals = array (
 
    array ( 'Hamster', 'Male',  10 ),
    array ( 'Hamster', 'Male', 5 ),
    array ( 'Cat', 'Female', 7 ),
    array ( 'Cat', 'Male', 15 ),
    array ( 'Dog', 'Male', 12 ),
    array ( 'Dog', 'Female', 1 ),
);
 

$onlyDogs = filter( 'Dog', $animals );
 
$onlyMaleDogs = filter( 'Male' , $onlyDogs );
 
print '<pre>'; print_r( $onlyDogs  ); print_r( $onlyMaleDogs  );


Saída:

Array
(
    [4] => Array
        (
            [0] => Dog
            [1] => Male
            [2] => 12
        )

    [5] => Array
        (
            [0] => Dog
            [1] => Female
            [2] => 1
        )

)
Array
(
    [4] => Array
        (
            [0] => Dog
            [1] => Male
            [2] => 12
        )

)


Ah! Mas você precisa contar também né? Sem problemas. Com uma adaptação da solução dada pelo João Batista nesse tópico, já que a sua estrutura conta com um índice a mais para o sexo do animal chegamos a isso:

function sum( $haystack ) {
 
    return array_reduce(
 
        $haystack,
 
        function( $reduced, $animal ) {
 
            $name = $animal[ 0 ];
 
            if ( ! isset( $reduced[ $name] ) ) {
                $reduced[$name] = 0;
            }
 
            $reduced[ $name ] += $animal[ 2 ];
 
            return $reduced;
        }
    );
}

 

É só invocar essa função passando o array que você quiser contar e pronto. Nesse exemplo, se você informar $animals terá a quantia de cada animal, separadinho.


Se informar $onlyDogs você receberá um array de índice único (Dog) e o total de cães existentes (16).

 

E se informar $onlyMaleDogs terá 15, já que um dos cãezinhos é fêmea.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Poxa, valeu pelas respostas gente, estou olhando código por código ainda. Vou só explicar como funciona o form, eu tenho um select box, de mais ou menos 30 opções de animais, o usuário seleciona 1, 2, 3, etc, etc, etc tipos de animais (infinito), informa o sexo desses animais, e logo depois informa a quantidade de cada animal. Não é necessário saber quantos tipos de animais o usuário selecionou, apenas o número total por genero e por espécie. A minha idéia é montar uma tabela do tipo

 

Animais Machos Femeas Total

Hamster 5 13 18

Rato 20 0 20

Boi 7 6 13

Gato 0 1 1

etc 0 2 2

etc 25 4 29

et 0 2 2

 

aqui está a array montada:

 

Array ( [0] => Rato heterogênico [1] => Array ( [0] => Rato heterogênico [1] => Machos [2] => 20 ) [2] => Array ( [0] => Rato isogênico [1] => Fêmeas [2] => 32 ) [3] => Array ( [0] => Rato isogênico [1] => Fêmeas [2] => 45 ) [4] => Array ( [0] => Anfíbio [1] => Machos [2] => 20 ) [5] => Array ( [0] => Camundongo heterogênico [1] => Fêmeas [2] => 24 ) [6] => Array ( [0] => Outra [1] => Fêmeas [2] => 500 ) [7] => Array ( [0] => Rato heterogênico [1] => Machos [2] => 20 ) [8] => Array ( [0] => Rato isogênico [1] => Fêmeas [2] => 16 ) [9] => Array ( [0] => Rato heterogênico [1] => Fêmeas [2] => 22 ) [10] => Array ( [0] => Rato isogênico [1] => Fêmeas [2] => 10 ) [11] => Array ( [0] => Rato isogênico [1] => Machos [2] => 96 ) [12] => Array ( [0] => Camundongo isogênico [1] => Machos [2] => 168 ) [13] => Array ( [0] => Rato isogênico [1] => Machos [2] => 50 ) [14] => Array ( [0] => Rato heterogênico [1] => Machos [2] => 40 ) [15] => Array ( [0] => Camundongo heterogênico [1] => Machos [2] => 24 ) [16] => Array ( [0] => Rato heterogênico [1] => Machos [2] => 150 ) [17] => Array ( [0] => Rato isogênico [1] => Machos [2] => 56 ) [18] => Array ( [0] => Rato heterogênico [1] => Fêmeas [2] => 16 ) [19] => Array ( [0] => Rato isogênico [1] => Machos [2] => 20 ) [20] => Array ( [0] => Camundongo isogênico [1] => Machos [2] => 60 ) [21] => Array ( [0] => Rato isogênico [1] => Machos [2] => 32 ) [22] => Array ( [0] => Rato heterogênico [1] => Machos [2] => 200 ) [23] => Array ( [0] => Rato isogênico [1] => Machos [2] => 160 ) [24] => Array ( [0] => Rato heterogênico [1] => Machos [2] => 50 ) [25] => Array ( [0] => Rato heterogênico [1] => Fêmeas [2] => 10 ) [26] => Array ( [0] => Camundongo isogênico [1] => Machos [2] => 20 ) [27] => Array ( [0] => Rato heterogênico [1] => Machos [2] => 10 ) )

Compartilhar este post


Link para o post
Compartilhar em outros sites

Se os dados do array vierem do jeito que você descreveu no primeiro post, a solução que apresentei funciona perfeitamente.

 

Você passaria o seu array de animais pela função filter() tendo como argumento o tipo do animal, vindo pelo por $_POST do primeiro dropdown.

 

Isso produziria um segundo array, com menos elementos. Então você passaria esse segundo array pela função, mas agora filtrando pelo sexo do animal, vindo por $_POST do segundo dropdown.

 

O resultado seria um terceiro array contendo apenas um determinado tipo de animal de um determinado sexo. Com isso é só contar pela segunda função.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Os dados não vem do $_POST, e sim do MYSQL, e vem concatenado do tipo: especie||genero||quantidade>>, mas até aqui eu consigo extrair cada informação com FOR. Alterando algumas configuções, cheguei no array abaixo, só não conseguí ainda visualizar uma forma de colocar isso na tabela que quero, mas acredito que esteja perto, uma vez que, na array ja foi possível dividir machos e fêmeas

 

Array

( [Rato heterogênico] =>

Array ( [Machos] => Array ( [0] => 20 [1] => 20 [2] => 72 [3] => 11 [4] => 40 [5] => 150 [6] => 4 [7] => 16 [8] => 200 [9] => 80 [10] => 160 [11] => 50 [12] => 20 [13] => 10 [14] => 10 )

[Fêmeas] => Array ( [0] => 22 [1] => 4 [2] => 16 [3] => 20 [4] => 10 ) )

 

[Rato isogênico] =>

Array ( [Fêmeas] => Array ( [0] => 32 [1] => 45 [2] => 16 [3] => 10 )

[Machos] => Array ( [0] => 20 [1] => 8 [2] => 96 [3] => 50 [4] => 56 [5] => 20 [6] => 32 [7] => 80 [8] => 160 ) )

[Anfíbio] =>

Array ( [Machos] => Array ( [0] => 20 ) )

[Camundongo heterogênico] =>

Array ( [Machos] => Array ( [0] => 216 [1] => 24 )

[Fêmeas] => Array ( [0] => 24 [1] => 24 ) )

[Outra] =>

Array ( [Fêmeas] => Array ( [0] => 500 ) )

[Camundongo isogênico] =>

Array ( [Machos] => Array ( [0] => 168 [1] => 60 [2] => 20 ) ) )

 

 

A idéia é montar isto (ex):

 

Animais Machos Femeas Total

Hamster 5 13 18

Rato 20 0 20

Boi 7 6 13

Gato 0 1 1

etc 0 2 2

etc 25 4 29

et 0 2 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Primeiro de tudo: Faz um favor? Pára de postar o [inline]print_r()[/inline] do(s) array(s) em texto plano na resposta porque não dá pra gente copiar e usar como array.

 

Até dá com algumas Expressões Regulares, mas é um trabalho do cão :P

 

Se for assim, posta o [inline]var_export()[/inline]. É igualmente feio, mas é utilizável. :thumbup:

 

Vamos lá... Corrigi meu post anterior para "Se os dados vêm do array...", assim tanto faz de onde vêm os dados, desde que seja um array. ;)

 

Eu não tenho idéia se esse último array bagunçado é isso que você pretende, arrumadinho. Mas partindo do pressuposto que seja, eis a dica de ouro.

 

Monte essa tabela do jeito que você está vendo, traduzindo ela em código PHP.

 

Com o PHP 5.4 é incrivelmente fácil, devido ao suporte a arrays no estilo JavaScript. Esse foi meu primeiro uso dessa versão e achei impressionante. ( :love:)

 

Pagação de pau de lado, afinal também é possível fazer em versões inferior à 5.4, depois de feito dê um [inline]print_r()[/inline] e veja (literalmente) como que é a estrutura disso que você quer e tente buscar um padrão nela.

 

Com a lógica encontrada, remonte o array. Você obviamente vai precisar iterar, e só parece difícil, mas É FÁCIL. Você refaz o array com 5 ou 6 linhas.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Valeu pelo toque bruno, depois de muiiiiiito tempo em cima do código, cheguei a resposta, posto aqui o resultado para conhecimento do pessoal, da forma como está eu obtive o resultado esperado:

 

foreach($especie as $linha){$grupo[$linha[0]][$linha[1]][] = $linha[2];}

echo '<table border=1>
<tr>
<td width="174"><font size="2" face="Arial, Helvetica, sans-serif">Espécie</font></td>
<td width="70" align="center"><font size="2" face="Arial, Helvetica, sans-serif">Machos</font></td>
<td width="70" align="center"><font size="2" face="Arial, Helvetica, sans-serif">Fêmeas</font></td>
<td width="45" align="right"><font size="2" face="Arial, Helvetica, sans-serif">Total</font></td>
</tr>
<tr>';

ksort($grupo);

foreach ($grupo as $x => $animal)
{

$totalM = 0;
$totalF = 0;

foreach($animal as $item => $valor){

if($item=='Machos'){
$totalM = array_sum($valor);
}
if($item=='Fêmeas'){
$totalF = array_sum($valor);
}
$total = ($totalM+$totalF);}


echo '<td><font size="2" face="Arial, Helvetica, sans-serif">'.$x.'</font></td>
<td align="center"><font size="2" face="Arial, Helvetica, sans-serif">'.$totalM.'</font></td>
<td align="center"><font size="2" face="Arial, Helvetica, sans-serif">'.$totalF.'</font></td>
<td align="right"><font size="2" face="Arial, Helvetica, sans-serif">'.$total.'</font></td>
</tr><tr>';}

echo '</table>';

 


Espécie || Machos || Fêmeas || Total

Anfíbio || 20 || 0 || 20

Camundongo heterogênico || 240 || 48 || 288

Camundongo isogênico || 248 || 0 || 248

Outra || 0 || 500 || 500

Rato heterogênico || 863 || 72 || 935

Rato isogênico || 522 || 103 || 625

Compartilhar este post


Link para o post
Compartilhar em outros sites

Legal, pelo menos um que não esperou a resposta pronta. :clap:

Bom, vou postar como eu fiz também a título de referência mas antes deixa eu explicar o que foi feito.

Transformando aquela tabela em array, com PHP 5.4 ficou assim:

 

$animals               = [ 'Male', 'Female', 'Total' ];
$animals['Hamster']    = [    5,      13,        18  ];
$animals['Rato']       = [   20,       0,        20  ];
$animals['Boi']        = [    7,       8,        13  ];

Certo? Agora visualizando esse array nós temos isso:

 

Array
(
    [0] => Male
    [1] => Female
    [2] => Total
    [Hamster] => Array
        (
            [0] => 5
            [1] => 13
            [2] => 18
        )

    [Rato] => Array
        (
            [0] => 20
            [1] => 0
            [2] => 20
        )

    [Boi] => Array
        (
            [0] => 7
            [1] => 8
            [2] => 13
        )

)

O três primeiros índices não interessam, pois representam apenas os Table Headings, numa analogia ao HTML.

 

Daí pra frente temos N sub-arrays sendo o nome do animal a chave e os valores SEMPRE na mesma ordem: Quantidade de machos, quantidade de fêmeas e total.

 

Descoberto o padrão que se repete, podemos facilmente remontar a estrutura:

$sorted = array();

foreach( $animals as $animal ) {

    list( $name, $gender, $amount ) = $animal;

    if( ! array_key_exists( $name, $sorted ) ) {
        $sorted[ $name ] = array( 0, 0, 0 );
    }

    $sorted[ $name ][ ( $gender == 'Male'  ? 0 : 1 )  ] += $amount;

    $sorted[ $name ][ 2 ] = $sorted[ $name ][ 0 ] + $sorted[ $name ][ 1 ];
}

Primeiro eu usei um list() porque eu sou tarado por ele quando trabalhando com arrays de estrutura fixa e conhecida. :grin:

 

O truque do IF, baseado na solução do array_reduce() do link para o tópico do João Batista que passei no post #8 é garantir que os três índices onde encaixaremos os resultados verdadeiros existam, evitando vários Notices.

 

Daí eu vou incrementar aquele zero definido por esse IF no primeiro ou no segundo índice da segunda dimensão, condicionando com o gênero do animal.

 

Um ternário simples resolve o caso, afinal, pelo menos no Reino Animal, só existem machos e fêmeas. :unsure:


Por fim, adicionamos no terceiro índice desse grupo a soma dos dois anteriores.

 

Inicialmente eu achei que poderia usar array_sum() mas cuidado, pois ao fazer isso a primeira iteração funcionará direitinho, já a partir da segunda array_sum() somaria o primeiro, o segundo e o terceiro índice, que a primeira iteração criou.

 

Bom, é isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.