Ir para conteúdo

POWERED BY:

Arquivado

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

Tiago Souza Ribeiro

Completar array para igualar tamanho com outro

Recommended Posts

Olá.

Como o título diz, quero preencher um array até o mesmo ter o mesmo tamanho de outro, ex:

array(
	"aka"=>array(
         "item1", "algo", "outro"
	),
	"bla"=>array(
         "alguma", "coisa"
	),
	"lol"=>"kkkk"
)

De alguma forma, quero que se torne nisso:

 

array(
	"aka"=>array(
         "item1", "algo", "outro"
	),
	"bla"=>array(
         "alguma", "coisa", "NULL"
	),
	"lol"=>array(
         "kkkk", "NULL", "NULL"
	)
)

> Os arrays tiveram seus tamanhos igualados preenchendo os valores que faltam com "NULL".

> A string foi transformada em um array e teve seu tamanho igualado também

Como posso fazer isso?

Lembrando que:

> Não tem como eu saber quantos valores o array tem

> Não tem como eu saber qual o tamanho do maior "sub-array"

> Não tem como eu saber se vai ter alguma string, se vai ser tudo string, se vai ser tudo array ou se vai ter algum array

Também seria útil alguma forma de detectar se todos valores do array são strings para aplicar os procedimentos anteriormente citados apenas se não fosse, ou se o array contém algum array como valor...

 

Obs: Não sei se ajuda, mas no final de tudo eu vou transformar esse array numa string. O que pretendo com isso é fazer um insert múltiplo. A string para o array que citei no começo do tópico seria:

INSERT INTO tabela_x (aka, bla, lol) VALUES ('item1', 'alguma', 'kkkk'), ('algo', 'coisa', NULL), ('outro', NULL, NULL)

Umas dúvidas que me surgiram ao digitar essa string:

> O NULL precisa de aspas ou é desse jeito aí mesmo? (sempre me esqueço de coisas simples...)

> Como eu faria para criar um array com todos os primeiros valores dos sub-arrays, outro com os segundos, etc...?

 

Aguardo alguma resposta

Até mais :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu tenho algumas idéias, você pode fazer o seguinte: Faz um foreach para percorrer todo seu array, até aqui tudo bem.

 

Dentro deste loop, você pode fazer a verificação se os valores de cada índice do array é tipo string, por exemplo:

<?php

$arr = array(1 => 'a', 2 => '2');
foreach($arr as $val):
   $string = is_string($val) ? true : false;
   $isNull = is_null($val) ? true : false;
endforeach;

?>

Fiz aqui mais ou menos, só tentei passar a lógica, porém certamente tá errado, mas é o caminho das pedras!

 

> Não tem como eu saber quantos valores o array tem

> Não tem como eu saber qual o tamanho do maior "sub-array"

> Não tem como eu saber se vai ter alguma string, se vai ser tudo string, se vai ser tudo array ou se vai ter algum array

Claro que tem, veja só:

 

1 e 2: Use a função count() para te retornar o tamanho do array, então consequentemente será o total de dados.

3: acabei de fazer um exemplo tosco acima.

 

Para você deixar 3 arrays com a mesma quantidade de dados, você pode usar a função count() pra saber qual deles tem maior número. Agora pra preencher com a mesma quantidade, deve ter alguma função, sei lá,só dar uma pesquisada e um pouco de lógica.

 

Espero ter ajudado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá. Obrigado por responder.

 

 

Essa parte de saber se é string: eu acho que se for fazer tudo que quero fazer da forma mais fácil vai ter muitos loops e vai ser uma lentidão danada. Sempre alguém me mostra uma forma de fazer algo sem loop quando eu pensava que não era possível, hehe.

Sobre a quantidade aí: o que quis dizer é que não será sempre 3 valores dentro do array. Muitas vezes em que posto algo aqui, o povo acha que terá sempre a quantidade fixa, por isso especifiquei logo.

Sobre função para preencher...: se não me engano eu vi uma vez uma função que faz isso no php.net. Já procurei bastante lá nas funções de array, mas nada... depois vou procurar mais.

 

Novamente, obrigado por responder :)

Compartilhar este post


Link para o post
Compartilhar em outros sites

A função para inserir valor no array é array_pop() e array_unshift(), não me lembro bem qual deles inserir no fim e no início.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu deveria te ensinar a fazer, sem postar a resposta, mas a explicação que bolei pareceu confusa sem o código:

 

<?php

$data = array(

   "aka" => array( "item1", "algo", "outro" ),

   "bla" => array( "alguma", "coisa" ),

   "lol" => "kkkk"
);

array_walk(

   $data,

   function( $value, $key ) use( &$data ) {

       $length = count( $value );

       if( $length < 3 ) {

           $data[ $key ] = array_merge(

               (array) $value,

               array_fill( $length, ( 3 - $length ), NULL )
           );
       }
   }
);

Mesmo que eu não devesse entrar nesse mérito em particular, vamos lá.

 

Eu utilizei um array_walk() para percorrer a matriz original, mas nada te impediria de usar um foreach ou um for-loop, por exemplo.

 

Eu utilizei uma Closure do PHP 5.3, se sua versão for inferior precisará usar create_function() (que tem uma sintaxe muito esquisita) ou optar pelas estruturas de loop citadas acima.

 

Dado o uso da Closure eu precisei trazer o array original pra dentro do escopo dela, daí o use(). Mas como também preciso que as modificações feitas reflitam externamente, passei-o por referência (daí o símbolo &).

 

Enfim...

 

A lógica em si consiste em contar o número de elementos da iteração corrente e, se menor que 3 (que você definiu) fazer alguma coisa.

 

Essa "alguma coisa" refere-se a criar um array composto por tantos NULL quantos você precisar. Para criar esse array com elementos variáveis, ao invés de infinitos IF's eu utilizei array_fill().

 

Essa função requer 3 argumentos:

 

  • Um índice para ser usado como primeiro índice desse array
     
  • Uma quantidade de elementos
     
  • Aquilo que será inserido

O primeiro argumento, tanto faz. Mas eu usei o mesmo valor da contagem para que ficasse tudo bonitinho. ^_^

 

O segundo argumento é o Grande Truque. Eu informei um valor matemático feito a partir da subtração do 3 que você definiu pela a quantidade atual.

 

IMPORTANTE! Essa operação não pode retornar menos que 1, caso contrário array_fill() produzirá um erro do tipo E_WARNING.

 

E o terceiro argumento é o NULL que você quer.

 

Nessa iteração o primeiro grupo de informações será ignorado, pois não satisfaz o IF definido.

 

No segundo, um array de um único índice será criado. E no terceiro, um de dois índices.

 

Mas isso sem inserir no array original não ajuda.

 

Daí entra o array_merge() para mesclar o array atual da iteração corrente, com esse "array falso" criado.

 

Porém, array_merge() espera um array como argumento mas seu terceiro índice não é um array, então forcei o cast para array para que isso:

 

"lol" => "kkkk"

Internamente passasse a ser isso:

 

"lol" => array( "kkkk" )

E voilà! Como o array foi passado por eferência, fora do array_walk() a estrutura estará completa.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom, está quase como eu quero :)

Um problema é que no seu método aí completa os arrays com a constante NULL, mas eu preciso que seja uma string "NULL" para usar no SQL. Isso é fácil de resolver, então é insignificante.

O problema principal é que nem sempre o maior array alí terá 3 valores, foi só um exemplo, por isso eu disse lá no post inicial que não têm como eu saber o tamanho do maior sub-array, às vezes pode ter uma quantidade, outras vezes outra. Assim, se eu tiver um dos sub-arrays com 4 valores, os demais devem ser igualados a 4 também, o mesmo com 5, 6, 7, etc...

Resolvendo este problema, a dúvida do tópico estará resolvida...

Sobre a versão do PHP: uso sempre a mais recente (5.4.6) pra evitar qualquer problema.

 

Fico no aguardo por alguma sugestão enquanto tento achar uma solução :)

Até mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ainda assim é fácil, só não é uma solução muito óbvia.

 

O que você teria de fazer seria simplesmente descobrir qual dos sub-arrays é o maior. O problema aqui está em saber em qual índice o maior sub-array se encontra para que você possa acessá-lo depois.

 

Obter tal valor é praticamente impossível sem iterar e ficar condicionando então, a solução mais prática seria por ordem na casa.

 

Uma vez que você ordena o array para que todos os sub-arrays sejam organizados do mais longo para o mais curto, basta acessar o índice zero.

 

Para fazer essa ordenação, usort() neles:

 

$data = array(

   "aka" => array( "item1", "algo", "outro" ),

   "bla" => array( "alguma", "coisa" ),

   "lol" => "kkkk",

   "largest" => range( 'a', 'z' ),
);

usort(

   $data,

   function( $a, $b ) {

       return count( $a ) < count( $b );
   }
);

Veja que adicionei um novo array de 26 elementos para ficar bem evidente.

 

Visualizando essa variável temos o sub-array com as 26 letras do alfabeto bem no topo, no índice zero como eu disse.

 

Agora é só contar (porque só nesse exemplo sabemos que a resposta e 26) e usar.

 

Por causa da Closure devemos localizar, no sentido de "trazer para dentro" e não de encontrar, o escopo da variável citada e substituir os números 3 literais que usamos anteriormente:

 

$largest = count( $data[ 0 ] );

array_walk(

   $data,

   function( $value, $key ) use( &$data, $largest ) {

       $length = count( $value );

       if( $length < $largest ) {

           $data[ $key ] = array_merge( (array) $value, array_fill( $length, ( $largest - $length ), NULL ) );
       }
   }
);

E pronto!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Rapaz, tu é um gênio :D

Porém há outro problema: o usort está trocando as chaves string por chaves numéricas...

Então resolva este problema,já que só tem este pra sua solução ficar pronta.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Certo...

Troquei o usort por uasort, e modifiquei o valor da variável $largest para count(array_keys($data)[0]), só que não está mais completando os arrays.

Tô com cabeça fraca hoje upset.gif

 

---- Edit:

Já resolvi!

Como disse, estou com cabeça fraca hoje...

$largest = count($data[array_keys($data)[0]]);

Vou só procurar uma forma melhor de pegar o primeiro índice, se houver. (Lembrei: key()) :P

 

Até mais ^^

Compartilhar este post


Link para o post
Compartilhar em outros sites

Foi falha minha... Estava com uasort() na ponta dos dedos mas não, eu quero fazer uma coisa mas o cérebro troll quer outra, quem sou eu pra questionar. :closedeyes:

 

A propósito, isso é desnecessário:

 

$largest = count($data[array_keys($data)[0]]);

É desnecessário. Como você mesmo solucionou, basta trocar, em $largest, por key():

 

$largest = count( $data[ key( $data ) ] );

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não sei se isso vai ajudar, mas fiz uma outra função. Mais simples, mas funciona. Sei que não vai usar, porque é simples e não transforma algo em array, mas resolvi compartilhar:

[ ATUALIZADO ]

Continua simples, mas agora verifica se é um array:

$a = array("1" => array("oi", "tchau"), "2" => "goo");

function completa($array_){
if(!is_array($array_)){
$vari = str_split($array_, strlen($array_));
}else{
$vari = $array_;
}
$B=array("NULL", "NULL");
if(count($vari) < 3){
if(count($vari) == 2){
$var = array_merge($vari, $B);
$array = array_splice($var, 0, 3);
print_r($array);
}
if(count($vari) == 1){
$var = array_merge($vari, $B);
print_r($var);
}
}
}

completa($a['2']);

OBS.: Simples no sentido de noob.

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.