Página 2 de 3

Enviado: 12 Fev 2008 21:40
por Maligno

Código: Selecionar todos

nMax := 0
nMes := 0
Aeval(aMeses,{|n,i|nMax := if(n>nMax, (nMes:=i,n), nMax)})
O bloco de código de AEval contém dois argumentos. Você sabe que este bloco avalia (evalua, como dizem alguns) elemento por elemento da matriz informada. No nosso caso, n é o elemento que está sendo avaliado e i é o número de ordem desse elemento dentro da matriz.

Como o valor de nMax depende do retorno do IF(), ao testar a expressão n > nMax, e sendo TRUE, faço o IF() retornar n, mas só depois (e tem de ser depois) de atribuir o número deste mês (i) a nMes.

Se sua dúvida ficou na sub-expressão (nMes:=i,n), apesar de meio estranha e incomum, ela é perfeitamente válida. Mas tem um porém. Sem parênteses, é erro de sintaxe. Com parênteses é uma expressão múltipla normal que, avaliada, retornará o último valor apurado, após a última vírgula. No caso, n. Eu só aproveitei essa característica pra também fazer a atribuição de nMes. Uma carona. :)

Enviado: 12 Fev 2008 21:54
por Pablo César
Maligno escreveu:(evalua, como dizem alguns)
Eu por exemplo, hihihi
Maligno escreveu:Se sua dúvida ficou na sub-expressão (nMes:=i,n), apesar de meio estranha e incomum, ela é perfeitamente válida.
Sim é a esta expressão que ainda não consigo entender.
Maligno escreveu:retornará o último valor apurado, após a última vírgula. No caso, n.
E o i para que seria ? Quê valor tem ?
Maligno escreveu:Eu só aproveitei essa característica pra também fazer a atribuição de nMes. Uma carona. :)
Sim, isso entendí e eu ia sugerir acrescentar ao seu exemplo inicial, mas achei que eu ia me embanar todo.

ordenar variaveis

Enviado: 12 Fev 2008 22:05
por Adalberto
Pablo César.

Sua pergunta se refere a essa linha?

LOCAL nIndice := 1 , nI

Então podemos modificar assim:

LOCAL nIndice := 1 , nI := 0

E só uma variável do tipo numérica, eu utilizo a notação Ungara, onde a primeira letra em minúscula diz o tipo da variável, neste caso nI quer dize que I e uma numérica. Assim nMaior.

anValor é: a= array, n=Numérico, Valor=Nome da variável

Perdão se exagere na explicação, foi com o propósito de deixar tudo claro respeito de este modo de nomear a variável.

Abraços e paz para você.

ordenar variaveis

Enviado: 12 Fev 2008 22:14
por Adalberto
Pablo César.

Por favor, não considere meu ultimo post, escrevi ele sem ler o post do maligno, foi um terrível descuido de minha parte, motivado pela conversação de minha mãe, com este filho seu que conversa e posta. ( já pedi perdão a minha mãe).

Perdoe Pablo César, e também perdão a todos os clippeiros do foro.

Enviado: 12 Fev 2008 22:21
por Maligno
Pablo César escreveu:
Maligno escreveu:(evalua, como dizem alguns)
Eu por exemplo, hihihi
Não só você. A tradução de "evaluation" não é muito clara. Por isso há quem use a tradução "evaluar", que não está tão errada. E você está perdoado, pois em espanhol traduz-se como "evaluar" ou "avaluar". :)
Maligno escreveu:Se sua dúvida ficou na sub-expressão (nMes:=i,n), apesar de meio estranha e incomum, ela é perfeitamente válida.
Sim é a esta expressão que ainda não consigo entender.
É uma expressão múltipla. Um exemplo prático para entender melhor:

Código: Selecionar todos

x :=  1,2,3,4,5
y := (1,2,3,4,5)
Um programa assim não compilaria por culpa da atribuição de x. Isso é erro de sintaxe. Mas y está sendo atribuído certinho. Ele receberá o valor 5, pois expressões múltiplas sempre retornam o último valor avaliado.
E o i para que seria ? Quê valor tem ?
A variável i no bloco de código é o índice (número de ordem) do elemento que está sendo avaliado naquele momento. Se o valor deste elemento for maior que nMax, i será utilizado para indicar o número do mês onde esse valor aparece.

Enviado: 12 Fev 2008 23:31
por Pablo César
Entendí e gostei (you are a genius !). No seu exemplo:

Código: Selecionar todos

aMeses:={12.22,33.44,55.78,11.01,66.38,23.34}
nMax := 0 
nMes := 0 
Aeval(aMeses,{|n,i|nMax := if(n>nMax, (nMes:=i,n), nMax)})
Pode ser traduzida em:

Código: Selecionar todos

aMeses:={12.22,33.44,55.78,11.01,66.38,23.34}
n:=0
nMax:=0
nMes:=0
FOR i=1 TO LEN(aMeses)
    n:=aMeses[i]
    IF n>nMax
       nMax:=n
       nMes:=i
    ELSE
       nMax:=nMax
    ENDIF
NEXT
? nMes
? nMax
Interessante a questão (nMes:=i,n) dentro do IF() além de atribuir a variável nMes com i o n atribui a variável nMax da condição IF(). Entendí, essa sentença cumpre duas funções. Obrigado pelo ensinamento (your trully a expert), tks.

ordenar variaveis

Enviado: 13 Fev 2008 01:02
por Adalberto
Pablo César,

Em sua tradução: ¿que aconteceria se os valores todos foram negativos?.

Iria mostrar 0 (zero) como maior.

Enviado: 13 Fev 2008 01:10
por Maligno
Mas zero é sempre maior que qualquer valor negativo, Adalberto. O único reparo que coloco no código do colega é que o ELSE do teste é desnecessário. Mas não tem tanto problema, já que é só um exemplo. Ele deve ter feito rápido e se distraiu.

Re: ordenar variaveis

Enviado: 13 Fev 2008 09:09
por Pablo César
Muito bem Adalberto, se todos os elementos forem negativos não iria funcionar direito (conforme meu exemplo anterior), mas veja o que fiz que funcionaria em ambos casos:

Código: Selecionar todos

aMeses:={-12.22,-33.44,-55.78,-11.01,-66.38,-23.34} // tudo negativo
tAllNeg:=.T.
FOR i=1 to LEN(aMeses)
    IF aMeses[i]>0
       tAllNeg:=.F.
    ENDIF
NEXT

nMax:=0
nMes:=0
FOR i=1 TO LEN(aMeses)
    IF tAllNeg
       n:=(aMeses[i])*-1
    ELSE
       n:=aMeses[i]
    ENDIF
    IF n>nMax
       nMax:=n
       nMes:=i
    ELSE
       nMax:=nMax
    ENDIF
NEXT
? nMes
? nMax
Agora com este exemplo, experimente asignando valores negativos e positivos mixtos ou até mesmo somente utdo positivo e funcionará normal. Agora cómo fazer tudo numa linha só, não sei se seria possível, quem sabe o mestre Maligno consiga...
O único reparo que coloco no código do colega é que o ELSE do teste é desnecessário. Mas não tem tanto problema, já que é só um exemplo. Ele deve ter feito rápido e se distraiu.
Com certeza o meu ELSE é desnecessário. Não foi distração minha, não. Eu apenas coloquei para evidenciar o seu exemplo no qual também é atribuido a si mesmo ...if(n>nMax, (nMes:=i,n), nMax)... Fiz isso para que o pessoal entendesse o que você tinha feito Maligno.

Enviado: 13 Fev 2008 10:15
por Maligno
Agora cómo fazer tudo numa linha só, não sei se seria possível
É só seguir o raciocínio de antes:

Código: Selecionar todos

for i := 1 to Len(aMeses)
   nMax := if((n:=aMeses[i]*if(tAllNeg,-1,1))>nMax,(nMes:=i,n)
next
Só não entendo porque mudar o sinal do valor, se a proposta é descobrir qual o maior valor. Se todos forem negativos e o problema for o zero inicial, é só iniciar nMax com um valor impossível. Algo do tipo -999999.

Usar o flag tAllNeg para indicar que há apenas valores negativos só para inverter os valores dos elementos não ajuda muito, porque se todos forem negativos, você inverte seus sinais, mas aí a busca deve se inverter também. Você precisará descobrir qual o menor valor. Valor este que, originalmente negativo, será o maior. :)

Enviado: 13 Fev 2008 10:47
por Pablo César
Quanto ao seu código: Beleza, funcionou corrigindo para:

Código: Selecionar todos

for i := 1 to Len(aMeses)
    nMax := if( (n:=aMeses[i]*if(tAllNeg,-1,1))>nMax,(nMes:=i,n), nMax )
next
Só não entendo porque mudar o sinal do valor, se a proposta é descobrir qual o maior valor. Se todos forem negativos e o problema for o zero inicial, é só iniciar nMax com um valor impossível. Algo do tipo -999999
Pois é, eu fiz isso e ainda achei que o resultado estava ERRADO. Mas eu me enganei e concordo contigo que não haveria necessidade de converter sinal, ora porquê ? Porque o resultado de todos os elementos negativos, será o maior aquele que for mais próximo do ZERO e convertendo este resultado muda o critério. Portanto apresento a versão corrigida:

Código: Selecionar todos

aMeses:={-12.22,-33.44,-55.78,-11.01,-66.38,-23.34}
nMax:=aMeses[1] // Corrigido conforme sugirido por Adalberto/Maligno
nMes:=0
FOR i=1 TO LEN(aMeses)
    n:=aMeses[i]
    IF n>nMax
       nMax:=n
       nMes:=i
    ENDIF
NEXT
? nMes
? nMax
ou no seu modo sintético:

Código: Selecionar todos

aMeses:={-12.22,-33.44,-55.78,-11.01,-66.38,-23.34}
nMax:=aMeses[1] // Corrigido conforme sugirido por Adalberto/Maligno
nMes:=0
Aeval(aMeses,{|n,i|nMax := if(n>nMax, (nMes:=i,n), nMax)})
? nMes
? nMax
Então podemos esquecer a razão de converter os elementos que estão como números negativos. Valeu Maligno pelo esclarecimento.

Obs.: Desculpe Maligno não ter respondido no chat, não te ví porque eu estava no Prompt de comando ocupado com os testes do número negativo e como o chat não possue recurso de avisar usuário quando está em outra sessão: acabei perdendo a oportunidade de dialogar contigo. E também não estavam ligadas as caixas de som. Sorry.

Enviado: 13 Fev 2008 10:57
por Maligno
Pablo César escreveu:Quanto ao seu código: Beleza, funcionou corrigindo para:
Pois é. Esqueci da última parte. Mas numa linha só acabou virando uma salada. :))) Ainda bem que é só por curiosidade mesmo.

Enviado: 13 Fev 2008 11:21
por marcos.gurupi
Kros colegas, obrigado a todos pelas dicas foi resolvido com o mesmo exemplo do Maligno.

Marcos Roberto.

ordenar variaveis

Enviado: 13 Fev 2008 12:06
por Adalberto
Pablo César,

Só com animo de contribuir.

Meu exemplo roda certinho encontra o valor maior sejam quaisquer tipos de valores, só negativos, positivos o misturado, e não precisa de esse valor -9999999.

Enviado: 13 Fev 2008 12:14
por Maligno
Justamente, Adalberto. O valor inicial -999999 sugerido também pode ser substituído pelo valor do primeiro elemento. Tanto o custo quanto efeito são os mesmos.