• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Engenheira

[Resolvido] sort em listas

17 mensagens neste tópico

Ja estive a ver em diversos sites e tenho aqui um livro de Python, mas em lado nenhum esta decentemente explicado como funciona a funcao sort das listas... Sei que pode receber 3 parametros: uma funcao para comparar, um atributo key e uma variavel chamada reverse que pode ser True ou False. Quanto a variavel reverse ja sei que se for True coloca a lista ordenada do fim para o principio. Quanto a funcao ainda nao entendi que parametros e que a funcao sort envia para dentro da funcao e quanto ao atributo key ainda nao percebi o que e, para que serve e como se usa...  :D

Alguem me ajuda?...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ok, ja tinha andado nesse site, so uma coisa:

a=[{'nome':'Joao', 'idade':'20'},{'nome':'Pedro', 'idade':'12'}, {'nome':'Rita', 'idade':'10'}]
a.sort(cmp)

o que e que recebe o cmp neste caso? E isso que eu ainda nao percebi... Recebe o primeiro elemento {'nome':'Joao', 'idade':'20'} e o segundo elemento {'nome':'Pedro', 'idade':'12'} para comparar os dois? E isto?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

provavelmente existem formas mais fáceis de fazer isto, mas admitindo que querias ordenar pela idade, isto deve dar:

>>> a=[{'nome':'Joao', 'idade':'20'},{'nome':'Pedro', 'idade':'12'}, {'nome':'Rita', 'idade':'10'}]
>>> a1=[(x["idade"], x) for x in a]
>>> a1.sort()
>>> a = [x for (k, x) in a1]

penso que por default 'cmp' devem ser as habituais funções de comparação, como tal não é preciso especificá-las (mas isto é o que alguém que não percebe nada de python pensa :D).

ordenar por nome também era semelhante (só que nesse caso a lista já estava ordenada).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

provavelmente existem formas mais fáceis de fazer isto, mas admitindo que querias ordenar pela idade, isto deve dar:

>>> a=[{'nome':'Joao', 'idade':'20'},{'nome':'Pedro', 'idade':'12'}, {'nome':'Rita', 'idade':'10'}]
>>> a1=[(x["idade"], x) for x in a]
>>> a1.sort()
>>> a = [x for (k, x) in a1]

ordenar por nome também era semelhante (só que nesse caso a lista já estava ordenada :)).

Errm...:D Nao percebo algumas das coisas que tens ai :D:( :D

>>> a1=[(x["idade"], x) for x in a] #que e isto??... (x['idade'], x) e tambem nao percebo o que e que esse for faz...

Vou chorar, quero C, C++, Java, qualquer coisa menos isto!!! :P:( que confusao...  :thumbdown:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

esse comando, a partir de {'nome':'Joao', 'idade':'20'}, cria (20,{'nome':'Joao', 'idade':'20'}), isto é, coloca o valor através do qual vais fazer a comparação fora.

>>> a=[{'nome':'Joao', 'idade':'20'},{'nome':'Filipe', 'idade':'12'}, {'nome':'Rita', 'idade':'10'}]
>>> a1=[(x_["idade"], x_) for x_ in a]
>>> a1
[('20', {'idade': '20', 'nome': 'Joao'}), ('12', {'idade': '12', 'nome': 'Filipe'}), ('10', {'idade': '10', 'nome': 'Rita'})]
>>> a1.sort()
>>> a1
[('10', {'idade': '10', 'nome': 'Rita'}), ('12', {'idade': '12', 'nome': 'Filipe'}), ('20', {'idade': '20', 'nome': 'Joao'})]
>>> a = [x for (_, x) in a1]
>>> a
[{'idade': '10', 'nome': 'Rita'}, {'idade': '12', 'nome': 'Filipe'}, {'idade': '20', 'nome': 'Joao'}]

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Hum... ok ja estou a perceber :D

So a cena que e mais chata e estar-se a copiar uma lista pra outra lista, ou seja, vou ficar com duas listas em memoria. Isto no caso destes exemplos pequenitos, tanto faz como fez, agora a lista que estou a usar no meu projecto contem prai uns 90 elementos obtidos da BD, nao sei se nao sera muito pesado... No entanto, se calhar nao ha outra maneira de fazer isto sem ser replicando a lista.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Hum... ok ja estou a perceber :D

So a cena que e mais chata e estar-se a copiar uma lista pra outra lista, ou seja, vou ficar com duas listas em memoria. Isto no caso destes exemplos pequenitos, tanto faz como fez, agora a lista que estou a usar no meu projecto contem prai uns 90 elementos obtidos da BD, nao sei se nao sera muito pesado... No entanto, se calhar nao ha outra maneira de fazer isto sem ser replicando a lista.

como já referi, não percebo nada de python (aliás, programei mais em python hoje do que no resto da minha vida :D) e provavelmente existem maneiras mais eficientes de fazer isso (eventualmente definindo a função 'cmp'), mas se as tuas listas são de 90 ou 100 ou até 1000 elementos não me parece que tenhas que te preocupar (agora se tivesses uma lista com uns milhões de elementos já era mais crítico).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

parece que arranjei forma de não ter que copiar a lista...

a.sort(lambda x, y : cmp(x["idade"],y["idade"]))

PS: é de mim ou o python é um bocado estúpido com a identação? é que nem um if then else consigo fazer sem que ele implique...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Python sucks!!! E so a minha opiniao, mas acho esta lingua uma valente m****!! Mas porque  e que eu nao posso fazer isto em C, ou Java... :'(

Infelizmente nao fui eu que escolhi a linguagem... :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ah e pra fazer ifs tens de fazer:

if pythonNaoPresta == True :
    resposta="Eu quero C ou Java JAA!!"
elif gostasDePython == True :
    resposta="Nao entendo como tal seja possivel..."
else:
    resposta="Me no likey

E assim esta identacao idiota...  :angry1:

A e o python nao e "um bocado" estupido com a identacao, no python tens de fazer a identacao pa ele perceber a diferenca entre as instrucoes, ou seja e completamente estupido.. :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Agora tenho outro problema... Com o nome resultou na perfeicao, mas agora tenho de ordenar por data. Para a data estou a usar objectos do tipo datetime, o codigo e o seguinte:

#(...)
elif request.POST['orderby']=='doc': #Verifica se o utilizador escolheu ordenar por doc (date of creation)
        auxlist=[(item["doc"], item) for item in userlist] #faz aquela coisa toda fixolas de criar uma nova lista
        auxlist.sort() #faz o sort (e aqui que da erro!)
        userlist=[item for(_,item) in auxlist] #volta a criar a lista de novo, mas ordenada

O erro que isto da e o seguinte:

Exception Type: TypeError

Exception Value: can't compare datetime.datetime to NoneType

O que e que se passa? Pelo que diz aqui: http://docs.python.org/lib/datetime-datetime.html e possivel comparar dois elementos do tipo datetime...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Alguem entende este erro?... E que eu nao estou a perceber o que q que se esta a passar... Se nao conseguir resolver isto acho que vou ter de fazer eu uma funcao de sort...  :bored:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

ok, aqui vai:

from django.shortcuts import render_to_response
from Manager.view_users.models import UserPoc, UserInfo
import datetime

def view_users(request):

    userPocs=UserPoc.objects.all()
    userInfos=UserInfo.objects.all()
    userlist=[]
    for u in userPocs:    
        for u2 in userInfos:
            if u2.user_name == u.user_name:                      #Aqui esta a construir uma lista com a informacao de ambas as tabelas
                userlist.append({'username':u.user_name,      #User_poc e User_info da base de dados (pra dps preencher 1 tabela)
                      'name':u.name,    #Ja ordena a lista por ordem alfabetica do nome
                      'position':u.position,
                      (...)
                      'domain':u2.domain,
                      'doc':u2.DOC,    #Quero ordenar a lista pelo DOC (Date Of Creation) que e um objecto do tipo datetime mas nao consigo... 
                      (...)
                      'accessgranted':access})
                break

    if request.POST['orderby']=='name':    #Codigo que funciona perfeitamente com o nome
        auxlist=[(item["name"], item) for item in userlist]
        auxlist.sort()
        userlist=[item for(_,item) in auxlist]

    elif request.POST['orderby']=='doc':    #Codigo que da o erro que eu referi acima
        auxlist=[(item["doc"], item) for item in userlist]
        auxlist.sort()    #E aqui que da erro
        userlist=[item for(_,item) in auxlist]
(...)

As classes usadas sao as seguintes:

from django.db import models

class UserInfo(models.Model):
    user_name = models.CharField(primary_key=True, maxlength=60)
    (...)
    domain = models.CharField(blank=True, maxlength=240)
    DOC = models.DateTimeField(null=True, blank=True)
    (...)
    accessgranted = models.TextField()
    def __str__(self):
        return self.user_name
    
    class Meta:
        db_table = 'User_info'

class UserPoc(models.Model):
    user_name = models.CharField(blank=False,primary_key=True, maxlength=60)
    name = models.CharField(blank=True, maxlength=240)
    (...)
    URL = models.CharField(blank=True, maxlength=120)

    def __str__(self):
        return self.name
    
    class Meta:
        db_table = 'User_poc'

e pronto e este o codigo.. Nao vou por o codigo todo pq e muito, mas esta ai o essencial... o que falta e onde estao os '(...)', sao apenas campos da classe que nao interessam e parte dos campos que estao a ser adicionados a lista, nao vale a pena estar a po-las aqui porque penso que sao irrelevantes para o problema em causa.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

ok, agora e que nao entendo mesmo, substitui o codigo que tinha acima por este (ordenamento usando o algoritmo de insercao):

    elif request.POST['orderby']=='doc':
        #auxlist=[(item["doc"], item) for item in userlist]
        #auxlist.sort()
        #userlist=[item for(_,item) in auxlist]
        counter=1
        while counter<len(userlist):
            index=userlist[counter]
            counter2=counter
            while counter2>0 and userlist[counter2-1]['doc']>index['doc']:
                userlist[counter2]=userlist[counter2-1]
                counter2=counter2-1
            userlist[counter2]=index
            counter=counter+1

tanto userlist[counter2]['doc'] como index['doc'] sao objectos do tipo datetime porque eu ja fiz essa verificacao... Mesmo assim continuo a obter o erro que obtinha acima... ja me estou a passar com isto!! :D preciso de ordenar a tabela de utilizadores pelo nome mas nao consigo...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ja descobri o problema.... Na base de dados alguem inseriu um registo sem DOC, resultado, quando chegava a esse registo dava este erro... No entanto eu nao tinha reparado no erro porque nao tinha reparado que ele ja ia no loop 22... entao pensava que era logo no primeiro registo, o que nao fazia sentido nenhum... :S

De qq forma obrigada a quem tentou ajudar :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora