Ordenar um array de objetos

1,555 views
Skip to first unread message

Josafá Filho

unread,
Jul 24, 2009, 7:27:33 AM7/24/09
to php...@googlegroups.com
All,

Tô com uma dúvida que pode ser fácil mas eu to viajando na maionese.

Eu quero saber como posso ordenar um array de objetos por um atributos do objeto. tipo assim

$pessoa1 = new Pessoa();
$pessoa1 = 'Huguinho';
$pessoa1->dataNascimento = '24/07/2009';

$pessoa2 = new Pessoa();
$pessoa2 = 'Zezinho';
$pessoa2->dataNascimento = '25/07/2009';

$pessoa3 = new Pessoa();
$pessoa3 = 'Luizinho';
$pessoa3->dataNascimento = '26/07/2009';


$array = array($pessoa2, $pessoa3, $pessoa1);

eu queria ordenar pelo campo dataNascimento de cada objeto.

pra ficar dessa maneira

array(

[0] => $pessoa1,
[1] => $pessoa2,
[2] => $pessoa3

)

--
Att,

Josafá Filho

Alwin Garside

unread,
Jul 24, 2009, 7:35:08 AM7/24/09
to php...@googlegroups.com
Use a funcão asort():
http://br.php.net/manual/pt_BR/function.asort.php

Exemplo:
<?php
$frutas = array("d" => "limao", "a" => "laranja", "b" => "banana", "c"
=> "melancia");
asort($frutas);
foreach( $frutas as $chave => $valor ){
echo "$chave = $valor\n";
}
?>

Resultado:
b = banana
a = laranja
d = limao
c = melancia


2009/7/24 Josafá Filho <josafa...@gmail.com>:
--
PHP Developer
TransIP - https://www.transip.nl/
E-mail: al...@transip.nl
Jabber: yoga...@gmail.com
MSN: yoga...@msn.com
Skype: yogarine
Twitter: http://twitter.com/yogarine
Mobile: +31 6 39 460 234

Alwin Garside

unread,
Jul 24, 2009, 7:36:23 AM7/24/09
to php...@googlegroups.com
Ah perai, nao li direito, quer ordenar pelo atributos? Ai não sei se
eh posivel... Acho que vai ter que escrever um funcão pra isso.

2009/7/24 Alwin Garside <yoga...@gmail.com>:

Josafá Filho

unread,
Jul 24, 2009, 7:47:25 AM7/24/09
to php...@googlegroups.com
era tudo que eu nao queria, mas se eh o jeito...
estou pensando em fazer assim transformar o atributo na key

ao inves disso

array(
[0] => $pessoa1,
[1] => $pessoa2,
[2] => $pessoa3
)

isso

array(
['24/07/2009'] => $pessoa1,
['25/07/2009'] => $pessoa2,
['26/07/2009'] => $pessoa3
)

ai eu ordeno pela key do array mantendo a referencia.

alguma outra sugestao?

2009/7/24 Alwin Garside <yoga...@gmail.com>



--
Att,

Josafá Filho

Rudinei Dias

unread,
Jul 24, 2009, 7:49:43 AM7/24/09
to php...@googlegroups.com
Como objeto não é um elemento que tenha um parâmetro de ordenação, e array não é adequado para isso, sugiro um solução alternativa. Coloque a data em padrão yyyymmdd como chave do array e ordene pela chave.
Exemplo:

$p = array();


$pessoa3 = new Pessoa();
$pessoa3 = 'Luizinho';
$pessoa3->dataNascimento = '26/07/2009';
$p['20090726']= $pessoa3;


$pessoa1 = new Pessoa();
$pessoa1 = 'Huguinho';
$pessoa1->dataNascimento = '24/07/2009';
$p['20090724']= $pessoa1;


$pessoa2 = new Pessoa();
$pessoa2 = 'Zezinho';
$pessoa2->dataNascimento = '25/07/2009';
$p['20090725']= $pessoa2;

ksort($p);
foreach ($p as $k => $obj) {
    echo $obj->dataNascimento.'<br />';
}

2009/7/24 Josafá Filho <josafa...@gmail.com>



--
-------------------------------------------------------------
Rudinei Dias

Felipe Ribeiro

unread,
Jul 24, 2009, 8:27:34 AM7/24/09
to php...@googlegroups.com
Existe uma solução mais "correta e elegante" do que as que foram
propostas: usando usort()

//Você cria uma função que compara duas pessoas

function comparapessoas(Pessoa $p1, Pessoa $p2) {
    if ($p1->dataNascimento == $p2->dataNascimento) {
        return 0;
    }
    return (strtotime($p1->dataNascimento) <
strtotime($p1->dataNascimento)) ? -1 : 1;
//usa o strtotime pra gerar o timestamp da data, já que no formato
dd/mm/yyyy não dá pra comparar direto.
}

//essa função ordena o array de acordo com a função comparativa
usort($pessoas,"compara_pessoas");

http://br.php.net/manual/en/function.usort.php

[ ]'s

2009/7/24 Rudinei Dias <rudine...@gmail.com>
--
Felipe Ribeiro
Zend PHP5 Certified Engineer
feli...@gmail.com
http://feliperibeiro.com
+55 83 9979-3161

Felipe Ribeiro

unread,
Jul 24, 2009, 8:28:36 AM7/24/09
to php...@googlegroups.com
Ups, correção, o nome da função precisa ser igual a string passada no
usort, então renomeia ela aí para compara_pessoas com o underline :)

2009/7/24 Felipe Ribeiro <feli...@gmail.com>:

Felipe Ribeiro

unread,
Jul 24, 2009, 8:29:14 AM7/24/09
to php...@googlegroups.com
Considere essa última..

function compara_pessoas(Pessoa $p1, Pessoa $p2) {
if ($p1->dataNascimento == $p2->dataNascimento) {
return 0;
}
return (strtotime($p1->dataNascimento) <
strtotime($p2->dataNascimento)) ? -1 : 1;
//usa o strtotime pra gerar o timestamp da data, já que no formato
dd/mm/yyyy não dá pra comparar direto.
}


2009/7/24 Felipe Ribeiro <feli...@gmail.com>:

Josafá Filho

unread,
Jul 24, 2009, 8:35:38 AM7/24/09
to php...@googlegroups.com
acho que tivemos a mesma ideia :D
a data neste formato que eu citei era só pra ficar mais fácil de entender estou usando unix time.

tambem tentei utilizar a função uksort()
com um metodo proprio de comparacao mas nao da certo nesse caso.

valeu ai galera :D

2009/7/24 Rudinei Dias <rudine...@gmail.com>



--
Att,

Josafá Filho

Rudinei Dias

unread,
Jul 24, 2009, 8:37:33 AM7/24/09
to php...@googlegroups.com
Ok. Felipe, é bem mais elegante. Certo.
Mas como fica a performance disto num array com 10000 objetos?
Será que é vantajoso? Eu faria este teste antes de usar uma função criada contra uma função built-in.


2009/7/24 Felipe Ribeiro <feli...@gmail.com>


Considere essa última..

function compara_pessoas(Pessoa $p1, Pessoa $p2) {
   if ($p1->dataNascimento == $p2->dataNascimento) {
       return 0;
   }
   return (strtotime($p1->dataNascimento) <
strtotime($p2->dataNascimento)) ? -1 : 1;
 //usa o strtotime pra gerar o timestamp da data, já que no formato
dd/mm/yyyy não dá pra comparar direto.
}


-------------------------------------------------------------
Rudinei Dias

Josafá Filho

unread,
Jul 24, 2009, 8:39:46 AM7/24/09
to php...@googlegroups.com
valeu ai felipe pela dica,

como eu estava usando uksort a funcao de comparacao recebia apenas os indices, o que nesse caso nao adiantava de nada.

2009/7/24 Josafá Filho <josafa...@gmail.com>



--
Att,

Josafá Filho

Felipe Ribeiro

unread,
Jul 24, 2009, 8:47:53 AM7/24/09
to php...@googlegroups.com
O custo é o teoricamente/aproximadamente o mesmo do uksort.
Afinal no uksort ele precisa fazer essa comparação só que ao invés de
ser num atributo é no índice do array, em ambos os casos essa
comparação tem um custo constante O(1) e o fator mais determinante
para o tempo de execução é o algoritmo que é usado para ordenação
(QuickSort, MergeSort, BubbleSort ou BozoSort :D).

Eu topo fazer esse teste com 10000 registros e já já posto o resultado

2009/7/24 Rudinei Dias <rudine...@gmail.com>:

Rudinei Dias

unread,
Jul 24, 2009, 8:59:26 AM7/24/09
to php...@googlegroups.com
Já fiz este teste.
Usando ksort, com a data no indice, obtive 0.0332.. segundos para um vetor de 10000 objetos.
Usando a solução com usort e a função, o tempo cresceu para 3.19... segundos. Ou seja, um crescimento exponencial.

Porém, a solução ksort não é a mais adequada para este problema, que traria o problema de substituição de objetos com a mesma data de nascimento. Nesse caso é necessário colocar mais um valor na chave para diferenciar os objetos, nem que seja um sequencial, para que a chave não se repita.
ex.
$p['20090726'.$indice_sequencial]= $pessoa3;

2009/7/24 Felipe Ribeiro <feli...@gmail.com>



--
-------------------------------------------------------------
Rudinei Dias

Felipe Ribeiro

unread,
Jul 24, 2009, 9:00:42 AM7/24/09
to php...@googlegroups.com
Ups, testei aqui, você tem razão Rudinei, usando ksort é muito mais
rápido, porque você tá manipulando índices e é executado todo em C,
enquanto o usort usa muito PHP. Porém não permite que duas pessoas
tenham a mesma data de nascimento.

2009/7/24 Felipe Ribeiro <feli...@gmail.com>:

Rudinei Dias

unread,
Jul 24, 2009, 9:06:49 AM7/24/09
to php...@googlegroups.com
Nesse caso é necessário colocar mais um valor na chave para diferenciar os objetos, nem que seja um sequencial, para que a chave não se repita.
ex.
$p['20090726'.$indice_sequencial]= $pessoa3;

2009/7/24 Felipe Ribeiro <feli...@gmail.com>




--
-------------------------------------------------------------
Rudinei Dias

Reply all
Reply to author
Forward
0 new messages