Ir para conteúdo

POWERED BY:

Arquivado

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

Edgard Lopes

[Resolvido] Como resgatar "algumas" variáveis de um array

Recommended Posts

Boa tarde a todos,

Como podem ver, sou novo no fórum. Tenho pouca experiência em PHP, porém, muito esforço para aprender. Procurei em diversos lugares (Manual dodo PHP, Livro do W. Jason Gilmore, etc.) a resposta para dúvida abaixo e não consegui resultado. Por tanto, o que preciso fazer não é simples:

 

Num array com diversos valores, preciso resgatar aqueles (valores) que estão entre os valores repetidos.

Por exemplo:

$produtos = array("F", "Ab", "Dg", "Gt", "F", "Nd", "MF", "Op", "KJ", "F", "DD", "Dj");

 

Preciso criar outro array com os valores que estão entre aqueles que se repetem (No caso acima, o valor que se repete é o "F"):

O array[0] com: "Ab", "Dg", "Gt"

O array[1] com: "Nd", "MF", "Op", "KJ"

O array[2] com: "DD", "Dj"

 

Resumindo, preciso transformar:

$produtos

 

Em:

 

$agrupamento[0]=("Ab"."Dg"."Gt");
$agrupamento[1]=("Nd"."MF"."Op"."KJ");
$agrupamento[2]=("DD"."Dj");

 

Detalhe: Os valores que se repetem são diferentes, existem 2 tipos e a quantidade varia. A quantidade e os tipos de valores que não se repetem também variam.

 

Desde já, agradeço à todos e desculpem-me por não postar nada antes dessa dúvida.

Compartilhar este post


Link para o post
Compartilhar em outros sites

cara... pensei num algoritmo aqui

 

-> descubra qual é "o valor que se repete"

-> itere sobre o array

-> compare a posição atual com o "valor que se repete"(conseguido anteriormente)

-> se o valor atual, for diferente do VQSR, guarde num array

-> caso seja igual, aumente 1 em um contador, e inicie assim, outro array bidimensional

-> faça os passos 3,4 e 5 até percorrer todo o array.

 

um simples for(), if(), e atribuições dão conta de fazer isso.

Para saber "qual o valor que se repete" existe nativamente um array_count_values()

http://www.php.net/manual/pt_BR/function.array-count-values.php

 

a chave que te devolver mais que 1, você sabe q "se repetiu".

é isso =)

 

Dessa forma dá para resolver. você pensou em alguma outra lógica ?

já fez algo ? Boa Sorte.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bolei uma solução aqui muio mais simples que a proposta pelo William, mas não seria certo te dar de mão beijada afinal, apesar de você ter dito que pesquisou, não expôs nenhuma tentativa.

 

Eu usei preg_split(), array_walk() e implode(), explode() e sprintf (esse por frescura) aliados à uma Closure-zinha simples (já que estou no PHP 5.3) e alguns comandos básicos da linguagem.

 

Mostre como fez ou tente fazer com o que passei e vejamos se consegue.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu usei preg_split(), array_walk() e implode() alidos à uma Closure-zinha simples

caraca! e isso é simples onde ? hauhauhauhaua

 

eu indiquei um algoritmo independente de linguagem.

você usou exclusivamente ferramentas do php, e uma que nem deveria existir numa linguagem orientada a objetos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

William, estamos em PHP certo? Então pra que eu vou bolar um algoritimo inteiro que possa ser aplicado até em Fortran (nussa, agora eu cavei fundo).

 

Sobre o recurso que não deveria existir, acho que diz com respeito à Closure. Não dá nem para comparar a facilidade e legibilidade e redução de código que esse recuro trouxe.

 

Facilidade e Leginilidade em oposição ao infame create_funtion().

 

Redução em vista de não ser preciso um método de classe/função à parte só para ser anexada como callback.

 

Posso ter usada várias funções, mas se fosse colocado em prática, não teria toda a complexidade in code que esse seu algoritimo aparenta ter.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cara, com muita das tretas nas quais eu não gostaria de ter feito, ficou assim:

<?php
      $produtos = Array( 'F' , 'Ab' , 'Dg' , 'Gt' , 'F' , 'Nd' , 'MF' , 'Op' , 'KJ' , 'F' , 'DD' , 'Dj' );
      $repetem = array_filter( array_count_values( $produtos ) );
      /**
       * Pegando os índices que se repetem no array
       * de produtos, assim vamos fazer uma iteração
       * sobre esses índices, pegando as posições do que está entre os mesmos
       */
      foreach( $repetem as $indice => $produto ) {
             if( $produto > 1 ) {
                    $repetidos [] = $indice;
             } 
      }
      /**
       * Pra cada índice repetido, vai pegar os índices 
       * dos items que estão entre os índices repetidos
       * @example Array( 'A' , 'B' , 'C' , 'A' ) 
       * Retorna: 1 [ B ] , 2 [ C ] 
       */
      foreach( $repetidos as $repetido ){
             for( $i = 0; $i < count( $produtos ) ; ++ $i ){
                   if( $produtos[ $i ] !== $repetido ) {
                       $position [] = $i;
                   } else {
                       $position [ 'N' ][] = $i;
                       unset( $produtos[ $i ] );
                   }
             }
      }
      /**
       * Removemos as variáveis $repetido, $i para uma sobrescrita
       */
      unset( $repetido , $i );
      /**
       * Pra cada índice repetido, faremos um loop que vai pegar os valores
       * que estão entre esses índices
       * @example [ 1 ] , [ 6 ] 
       * Retorna: 2 , 3 , 4 , 5 
       */
      foreach( $position[ 'N' ] as $repetido ) {
               for( $i = ++$repetido; $i < current( $position[ 'N' ] ); ++$i ) {
                    $Entre[ $repetido ][] = $produtos[ $i ];
                    unset( $produtos[ $i ] );
               }
               next( $position[ 'N' ] );
      }
      $Produtos[] = $produtos; 
      $Entre = array_merge_recursive( $Produtos , $Entre );
      echo '<pre>';
      print_r( $Entre );

 

Saída:

Array
(
   [0] => Array
       (
           [10] => DD
           [11] => Dj
       )

   [1] => Array
       (
           [0] => Ab
           [1] => Dg
           [2] => Gt
       )

   [2] => Array
       (
           [0] => Nd
           [1] => MF
           [2] => Op
           [3] => KJ
       )

)

 

Tinha que pensar nos produtos que sobraram no array, em um índice que não se repetia mais, veja o próprio exemplo que você deu, o F se repete três vezes, quer dizer, que o loop só ia montar 2 arrays, o que estava entre o primeiro , e depois do segundo pro terceiro, mas não do terceiro pra mais ..

Compartilhar este post


Link para o post
Compartilhar em outros sites

utlizo clousures em javascript, realmente são ótimas.

 

PHP é q não deveria ter incoporado elas

 

William, estamos em PHP certo?

não sei.

Então pra que eu vou bolar um algoritimo inteiro que possa ser aplicado até em Fortran (nussa, agora eu cavei fundo).

Logica de Programação, e programação básica.

você não usa PDO para poder mudar de banco ?

 

eu uso programação básica para poder mudar de linguagem, sem precisar reaprender tudo.

 

Sobre o recurso que não deveria existir, acho que diz com respeito à Closure.

sim. Não deveriamos ter clousures em php.

 

Não dá nem para comparar a facilidade e legibilidade e redução de código que esse recuro trouxe.

clousures em linguagens OO, ferem conceitos do OO

 

 

 

Facilidade e Leginilidade em oposição ao infame create_funtion().

outra gambiarra.

 

Redução em vista de não ser preciso um método de classe/função à parte só para ser anexada como callback.

Design Patterns existem para isso!

 

 

Posso ter usada várias funções, mas se fosse colocado em prática,

..

 

não teria toda a complexidade in code que esse seu algoritimo aparenta ter.

poxa.. um for(), um if() e um contador complexos ?

caramba :lol: que mundo doido.

 

 

Você é "programador php" ?

 

Eu sou programador.

Compartilhar este post


Link para o post
Compartilhar em outros sites

William, estamos em PHP certo?

não sei.

<_<

 

Então pra que eu vou bolar um algoritimo inteiro que possa ser aplicado até em Fortran (nussa, agora eu cavei fundo).

Logica de Programação, e programação básica.

você não usa PDO para poder mudar de banco ?

 

eu uso programação básica para poder mudar de linguagem, sem precisar reaprender tudo.

À parte do PHP, só uso jQuery, HTML básico e CSS. Pouquissimas vezes precisei, por exemplo, de algo do PHP no JavaScript.

 

Pelo menos pra mim, não há necessidade de aprender dezenas de coisas que é quase certeza que não vou utlizar.

 

Não dá nem para comparar a facilidade e legibilidade e redução de código que esse recuro trouxe.

clousures em linguagens OO, ferem conceitos do OO

Nem sempre.

 

Facilidade e Leginilidade em oposição ao infame create_funtion().

outra gambiarra.

Que ainda assim ajudou muita gente no passado e foi mantida pelos próprio desenvolvedores durante muito tempo.

 

Redução em vista de não ser preciso um método de classe/função à parte só para ser anexada como callback.

Design Patterns existem para isso!

Vai lendo...

 

não teria toda a complexidade in code que esse seu algoritimo aparenta ter.

poxa.. um for(), um if() e um contador complexos ?

caramba :lol: que mundo doido.

Você está levando muito ao pé da letra o escopo do termo complexo

 

Você é "programador php" ?

 

Eu sou programador.

Que bom pra você :D

 

Bpm, já que o Andrey postou a versão dele, postarei a minha também. Não sei se o Andrey se baseou na lógica postada por você, William, mas se sim ou se não, veja com carinho e reflita com o que eu disse sobre complexidade in code

 

E depois olhe como ficou mais simples aforma como eu fiz.

 

Pode não ser perfeita, afinal fiz em 5 minutinhos, e foquei apenas no que o amigo Edgar disse precisar. Pode ser que hajam bugs ou que não seja compatível com qualquer sequencia, mas e daí.

 

$produtos = array("F", "Ab", "Dg", "Gt", "F", "Nd", "MF", "Op", "KJ", "F", "DD", "Dj");

$target = 'F';

$splitted = preg_split( sprintf( '/\b%s\b/', $target ), implode( ',', $produtos ) );

$cleaned = array();

array_walk(

   $splitted,

   function( $item ) use( &$cleaned ) {

       if( ! empty( $item ) ) {

           $cleaned[] = explode( ',', trim( $item, ',' ) );
       }
   }
);

var_dump( $cleaned );

/**
* Saída:
*
* array
*   0 => 
*     array
*       0 => string 'Ab' (length=2)
*       1 => string 'Dg' (length=2)
*       2 => string 'Gt' (length=2)
*   1 => 
*     array
*       0 => string 'Nd' (length=2)
*       1 => string 'MF' (length=2)
*       2 => string 'Op' (length=2)
*       3 => string 'KJ' (length=2)
*   2 => 
*     array
*       0 => string 'DD' (length=2)
*       1 => string 'Dj' (length=2)
*/

Pode ser que nesse fragmento de código, uma Closure como callback pudesse ser evitada.

 

Apesar disso, você não citou "Design Patterns" para se evitar isso, mas não mencionou qual simplificaria ainda mais do que uma Closure como callback.

 

Não sei você, mas quando eu falo (ou escrevo) algo, o faço completamente, expondo tudo aquilo que tenho em mãos sobre o assunto de uma só vez.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bruno Augusto, lamento em dizer isso, mas eu usei sim, a idéia do William Bruno, porque o que eu já imaginava era isso mesmo. Como falei com ele via PM, não tem motivo de usar preg_ como ele mesmo disse, já que a minha idéia era usar o grep pra pegar as posições dos índices no array. Você definiu um trajeto pra quem se repete no array:

$target = 'F';

Agora me diz, e se o cara tiver D , P , Z, X que se repete ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Dá para eliminar o uso do

$target = 'F';

 

Usando

max( array_flip( array_count_values( $produtos ) ) );

 

 

Agora se existir mais de um valor repetido...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ok Carlos, temos então:

$produtos = array("F", "Ab", "Dg", "Gt", "F", "Nd", "MF", "Op", "KJ", "F", "DD", "Dj" , "D" , "I" , "D" );

 

Saída:

Array
(
   [0] => Array
       (
           [0] => F
           [1] => Ab
           [2] => Dg
           [3] => Gt
           [4] => F
           [5] => Nd
           [6] => MF
           [7] => Op
           [8] => KJ
           [9] => F
           [10] => DD
           [11] => Dj
           [12] => D
       )

   [1] => Array
       (
           [0] => D
       )

)

 

Como você mesmo disse, se tiver mais de um valor repetido ..

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mais uma contribuição.

$produtos = array("F", "Ab", "Dg", "Gt", "F", "Nd", "MF", "Op", "KJ", "F", "DD", "Dj");

# o rsultado final
$resultado = array();

#as chaves dos limitadores
$indices = array();

#variável auxiliar
$array = array();

/*
Guarda as chaves das posições dos limitadores
*/
foreach($produtos as $chave => $valor){
 if($valor === 'F'){
   $indices[] = $chave;
 }
}

/*
O array resultado guarda os valores entre o limitadores.Por exemplo, entre o 1º e o 2º limitadores
há Ab,Dg e Gt. Entre o 2º e o 3º há Nd, MF, Op e KJ. Os dois últimos valores não são armazenados porque
não há mais limitadores: um bug.
Se o array tem limites ímpares os últimos valores não são
capturados. Por isso, no final, eu acrescentei mais um limitador para corrigir o bug.
*/
if(count($indices) % 2 !== 0){
   $produtos[] = 'F';    
   $indices[] = key($produtos);
}

foreach($produtos as $chave => $valor){ 
   if(!in_array($chave, $indices)){
$array[] = $valor;
   }else{
if(count($array) != 0){
    $resultado[] = implode(" ",$array);	   
    $array = array();	    
}
   }    
}


var_dump($resultado);
/*
array(
   0 => Ab Dg Gt,
   1 => Nd MF Op KJ,
   2 => DD Dj
)

*/

Compartilhar este post


Link para o post
Compartilhar em outros sites

menino_levado, assim não vale, você está falando qual índice ele vai procurar .. o negócio e pegar tudo que está entre todos repetidos.

 

Você colocou que não há mais limitadores, falou que é um 'bug', lógico que não, se acabou os índices, o resto é resto, não tem mais nada que se repete dali pra frente, então você ainda tem que adicionar esses últimos ao novo array.

Compartilhar este post


Link para o post
Compartilhar em outros sites

@menino_levado

 

Agora me diz, e se o cara tiver D , P , Z, X que se repete ?

 

você vai fazer a verificação do limitadores manualmente ?

 

 

Tive uma idéia para esse problema. Talvez possa ter algum bug, mas parece funcionar.

 

<?php

$produtos = array("F", "Ab", "DD", "Gt", "F", "Nd", "MF", "Op", "KJ", "F", "DD", "MF");

array_walk( 
   array_filter( 
       array_count_values( $produtos ),
       function( $filter )
       {
    return ( $filter > 1 );
       } ),
   function( $item, $key ) use ( &$cleaned, $produtos )
   {
foreach( preg_split( sprintf( '/\b%s\b/', $key ), implode( ',', $produtos ) ) as $item )
{
    if( ! empty( $item ) ) $cleaned[ $key ] [ ] = explode( ',', trim( $item, ',' ) );
}
   }
);

var_dump( $cleaned );

?>

 

Saída

 

array
 'F' => 
   array
     0 => 
       array
         0 => string 'Ab' (length=2)
         1 => string 'DD' (length=2)
         2 => string 'Gt' (length=2)
     1 => 
       array
         0 => string 'Nd' (length=2)
         1 => string 'MF' (length=2)
         2 => string 'Op' (length=2)
         3 => string 'KJ' (length=2)
     2 => 
       array
         0 => string 'DD' (length=2)
         1 => string 'MF' (length=2)
 'DD' => 
   array
     0 => 
       array
         0 => string 'F' (length=1)
         1 => string 'Ab' (length=2)
     1 => 
       array
         0 => string 'Gt' (length=2)
         1 => string 'F' (length=1)
         2 => string 'Nd' (length=2)
         3 => string 'MF' (length=2)
         4 => string 'Op' (length=2)
         5 => string 'KJ' (length=2)
         6 => string 'F' (length=1)
     2 => 
       array
         0 => string 'MF' (length=2)
 'MF' => 
   array
     0 => 
       array
         0 => string 'F' (length=1)
         1 => string 'Ab' (length=2)
         2 => string 'DD' (length=2)
         3 => string 'Gt' (length=2)
         4 => string 'F' (length=1)
         5 => string 'Nd' (length=2)
     1 => 
       array
         0 => string 'Op' (length=2)
         1 => string 'KJ' (length=2)
         2 => string 'F' (length=1)
         3 => string 'DD' (length=2)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bruno Augusto, lamento em dizer isso, mas eu usei sim, a idéia do William Bruno, porque o que eu já imaginava era isso mesmo. Como falei com ele via PM, não tem motivo de usar preg_ como ele mesmo disse, já que a minha idéia era usar o grep pra pegar as posições dos índices no array. Você definiu um trajeto pra quem se repete no array:

$target = 'F';

Agora me diz, e se o cara tiver D , P , Z, X que se repete ?

Não lamente. Na Internet nada se cria, nada se perde, tudo se copia (Aleksander Mandic) ^_^

 

Eu olhei diretamente para o problema que o Edgar tinha, não atentei para o "nesse caso quem se repete é o F". Justo por isso supus que apenas uma única letra (ou conjunto de letras) seria o alvo da separação.

 

E por isso separei-a em uma variável.

 

Eu imaginei como uma função onde é conhecido o limitador.

Mesma resposta acima vale para ti também. Num primeiro momento, foi tudo o que pensei.

 

@Carlos Coelho, parabéns :clap:

Compartilhar este post


Link para o post
Compartilhar em outros sites

se por acaso acontecer algo do tipo

$produtos = array("F", "Ab", "DD", "Gt", "F", "Nd", "MF", "DD", "KJ", "F", "DD", "MF");

 

Temos o F e o DD como delimitadores, porém, o DD começa antes de terminar um dos Fs..

 

e aí ?? rss

 

 

no entanto, se o padrão for sempre a letra 'F' e não houver outras letras que se repitam, então uma solução manual pode ser mais eficaz.

 

 

acredito que a solução mais eficaz seja estabelecer um padrão na origem do que tentar fazer gambiarras por falta de um padrão "decente"

Compartilhar este post


Link para o post
Compartilhar em outros sites

Detalhe: Os valores que se repetem são diferentes, existem 2 tipos e a quantidade varia. A quantidade e os tipos de valores que não se repetem também variam.

 

Em nenhum momento o criador do tópico disse como seria a saida, se tivéssemos mais de um delimitador.

Portanto, assumo que só terei um delimitador, até que o problema seja melhor explicado.

 

<?php

$produtos = array("F", "Ab", "Dg", "Gt", "F", "Nd", "MF", "Op", "KJ", "F", "DD", "Dj");
$delimitador = max( array_flip( array_count_values( $produtos ) ) );

$out = Array();
for( $i=0, $j=0, $count=count($produtos); $i<$count; $i++ )
{
	if( $produtos[$i]==$delimitador )
		$j++;
	else
		$out[ $j ][] = $produtos[$i];
}
echo '<pre>';
var_dump( $out );

output

array(3) {
 [1]=>
 array(3) {
   [0]=>
   string(2) "Ab"
   [1]=>
   string(2) "Dg"
   [2]=>
   string(2) "Gt"
 }
 [2]=>
 array(4) {
   [0]=>
   string(2) "Nd"
   [1]=>
   string(2) "MF"
   [2]=>
   string(2) "Op"
   [3]=>
   string(2) "KJ"
 }
 [3]=>
 array(2) {
   [0]=>
   string(2) "DD"
   [1]=>
   string(2) "Dj"
 }
}

 

Não sei onde ou como cada um aqui aprendeu a programar, mas de onde eu vim, me pediam para descrever os procedimentos do meu código.

Me diga vocês, quais são as etapas do código de vcs. Transforme em algorítmo, assim como comecei a minha solução.

Compartilhar este post


Link para o post
Compartilhar em outros sites

William Bruno, seu código dá problema se tiver mais de um produto repetido no array, agora .. já que a brincadeira é não fazer gambiarra, e funcionar com inúmeros produtos repetidos, segue a solução:

<?php
       $Produtos = Array( 'F' , 'Ab' , 'Dg' , 'Gt' , 'F' , 'Nd' , 'MF' , 'Op' , 'KJ' , 'F' , 'DD' , 'Dj' , 'DD' , 'I' , 'H' , 'J' , 'I' );
       function getProductsBetweenDuplicates( Array $Array ){
              $count = array_count_values( $Array );
              $i = 0;
              foreach( $Array as $Data ){
                       if( $count[ $Data ] > 1 ){
                            if( count( $New ) ){
                                  ++$i;
                            } 
                       } else {
                           $New[ $i ][] = $Data;
                       }
              }
              return $New;
       }
       echo '<pre>';
       print_r( getProductsBetweenDuplicates( $Produtos ) );

 

Saída:

Array
(
   [0] => Array
       (
           [0] => Ab
           [1] => Dg
           [2] => Gt
       )

   [1] => Array
       (
           [0] => Nd
           [1] => MF
           [2] => Op
           [3] => KJ
       )

   [3] => Array
       (
           [0] => Dj
       )

   [5] => Array
       (
           [0] => H
           [1] => J
       )

)

 

Carlos Coelho, não preciso fazer complicação no código não brother, o William Bruno deu a chave pra abrir a porta, basta virar, o meu código acima, usei um loop baseado no algoritmo do William, e resolvi o problema pra inúmeros produtos duplicados, já o código do Bruno Augusto, dá problema se tiver vários duplicados ..

 

o autor do tópico deu um exemplo com uma unica repetição, então estamos afirmando que só vai repetir uma vez, beleza .. assim sua idéia funciona, mas eu estou falando, se os produtos se repetirem várias vezes ..

 

Voltando ao meu código, outro tipo de saída no caso dos produtos repetidos estiverem um entre o outro, impedindo que o valor repetido seja removido e colocado dentro do novo array, então veja a situação:

$Produtos = Array( 'F' , 'Ab' , 'Dg' , 'Gt' , 'F' , 'Nd' , 'MF' , 'Op' , 'KJ' ,
                  'F' , 'DD' , 'Dj' , 'DD' , 'I' , 'H' , 'J' , 'I' , 'H' , 'Z' , 'H' );

 

Temos I , H , J [ Não Repetido ] , I , H , depois o Z entre outro H, saída:

Array
(
   [0] => Array
       (
           [0] => Ab
           [1] => Dg
           [2] => Gt
       )

   [1] => Array
       (
           [0] => Nd
           [1] => MF
           [2] => Op
           [3] => KJ
       )

   [3] => Array
       (
           [0] => Dj
       )

   [6] => Array
       (
           [0] => J
       )

   [8] => Array
       (
           [0] => Z
       )

)

 

;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

William Bruno, seu código dá problema se tiver mais de um produto repetido no array

não é problema. Apenas não é o objetivo do algoritmo.

 

O autor não disse oque deve acontecer caso tenhamos mais de uma repetição.

Ele apresentou um problema.

Deu uma entrada

E deu uma saida.

 

Formulei um algoritmo para isso. Pronto.

Se precisar de mais de uma repetição, ele deve explicar.

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.