Página 1 de 1

aSort com valor negativo + texto

Enviado: 13 Fev 2015 11:46
por Junior
Bom dia, Srs !

Estou enfrentando uma dificuldade na ordenação de uma array com apenas 2 elementos, sendo um numérico e outro texto. O elemento numérico apresenta valores negativos que devem estar em primeiro na ordenação. Quanto menor, mais importante.

Código: Selecionar todos

Curva   Valor
A2      -100
A1       200
A3      -300
A1      -300
O Exemplo acima mostra os valores desordenados, abaixo os ordenados, respeitando sempre VALOR + CURVA:

Código: Selecionar todos

Curva  Valor
A1      -300
A3      -300
A2      -100
A1       200
Porém, o bendito do ASORT não entende assim, ele faz uma mescla de bagunça na ordenação que eu ainda não consegui entender. Já tentei concatenar valores com ASC, STR mas não adianta. A única ordenação correta é quando eu passo apenas o elemento numérico, sem considerar o texto (curva).

Funciona:

Código: Selecionar todos

aSort(aDados02,,, {|x,y| x[1] < y[1]})
Não funciona:

Código: Selecionar todos

aSort(aDados02,,, {|x,y| STR(x[1])+y[2] < STR(y[1])+y[2]})
aSort(aDados02,,, {|x,y| x[1]+ASC(y[2]) < y[1]+ASC(y[2])})
Ou seja, ao que parece o ASORT pira quando concateno elementos de tipos diferentes quando o elemento numérico possui valores negativos.

Alguma luz?

Vale lembrar que esse "não funciona", apenas não funciona mesmo quando existem valores negativos no elemento numérico, para números positivos, quando eu concateno com STR(), tudo fica OK!

Obrigado sempre por tudo, já frequentei essa comunidade há muito tempo atrás, uma pena os rumos da vida nos indicarem outras linguagens.

Abraço a todos !
Junior

aSort com valor negativo + texto

Enviado: 13 Fev 2015 14:31
por Toledo
Amigo, tente o seguinte:

Código: Selecionar todos

aSort(aDados02,,, {|x,y| STR(x[2])+x[1] < STR(y[2])+y[1]})
No seu exemplo, observe que você está usando STR(x[1])+y[2] < STR(y[1])+y[2]}), misturando elementos x e y numa mesma combinação. E também, se na matriz o segundo elemento é o valor, então STR() tem que ser usado com o elemento 2.

Abraços,

aSort com valor negativo + texto

Enviado: 13 Fev 2015 14:35
por Junior
Toledo! Prazer em falar com você novamente.

Amigo, peço perdão pelo equívoco, foi um erro de digitação, na verdade o elemento X é sim comparado com o elemento Y:

Código: Selecionar todos

aSort(aDados02,,, {|x,y| STR(x[2],12,2)+x[1] < STR(y[2],12,2)+y[1]})
O código acima só funciona quando o elemento numérico apresenta valores positivos, já se algum negativo for encontrado, a ordenação fica maluca.

Obrigado pelo retorno e um abraço!
Junior

aSort com valor negativo + texto

Enviado: 13 Fev 2015 15:44
por sambomb

Código: Selecionar todos

aSort(aDados02,,, {|x,y| If(x[2]<0,"A","B")+STR(Abs(x[2]),12,2)+x[1] < If(y[2]<0,"A","B")+STR(Abs(y[2]),12,2)+y[1]})
Tente assim
Coloquei um texto padrão para negativos ( A ) e para positivos ( B ) e removi o módulo do valor original.
Assim ficará da seguinte forma:

Código: Selecionar todos

1	Curva  Valor Texto para comparação
2	A1      -300   A300A1
3	A3      -300   A300A3
4	A2      -100   A300A2
5	A1       200   B200A1

aSort com valor negativo + texto

Enviado: 13 Fev 2015 17:22
por Jairo Maia
Olá Júnior,

Se a sugestão do Samir também não funcionar (testei aqui e não deu), não vejo outra forma pra você ter esse resultado senão ardenando os campos separadamente. Tente assim e veja se funciona:

Código: Selecionar todos

aSort( aDados02,,, { |x,y| x[1] < y[1]  } )  // ordena o primeiro elemento
aSort( aDados02,,, { |x,y| x[2] < y[2]  } )  // depois ordena o segundo elemento

aSort com valor negativo + texto

Enviado: 13 Fev 2015 19:36
por ANDRIL
Junior escreveu:Alguma luz?
Compare a matriz com todos os 2 elementos, tente assim:

Código: Selecionar todos

aSort(aDados02,,,{|x,y| x[1]<y[1].and.x[2]<y[2]})
Ate+

aSort com valor negativo + texto

Enviado: 15 Fev 2015 23:25
por Eolo
Junior,
Se a ASORT() tá fazendo doce, engane ela!
Testei aqui e funcionou perfeito.

A idéia:
- identifique o menor valor negativo (no caso, -300)
- some 300 em todos os elementos da matriz
- o menor valor, então, se transforma em ZERO
- e agora a matriz não tem mais números negativos
- aplique o ASORT
- subtraia 300 em todos os elementos da matriz
- feito.

Código: Selecionar todos

mat:={}
aadd(mat,{"a2",-100})
aadd(mat,{"a1", 200})
aadd(mat,{"a3",-300})
aadd(mat,{"a1",-300})
const=0
* APONTA O MENOR VALOR
for x=1 to len(mat)
  min(const,mat[x,2])
next
* CONST vai conter -300
* MOSTRA VALORES DESORDENADOS
for x=1 to len(mat)
  ?mat[x,1]
  ?mat[x,2]
next
if const<0
  for x=1 to len(mat)
    * MENOR VALOR PASSA A SER ZERO
    * SOMEM OS VALORES NEGATIVOS
    mat[x,2]:=mat[x,2]+const
  next
endi
* ORDENA CONFORME DESEJADO

*mat:=aSort(mat,,, {|x,y| x[2] < y[2]})

* pegando carona na sugestão do ANDRIL
mat:=aSort(mat,,,{|x,y| x[1]<y[1].and.x[2]<y[2]})

if const<0
  for x=1 to len(mat)
    * FAZ VALORES VOLTAR AOS VALORES ORIGINAIS, COM OS NEGATIVOS
    mat[x,2]:=mat[x,2]-const
  next
endi
* MOSTRA VALORES ORDENADOS CONFORME DESEJADO
for x=1 to len(mat)
  ?mat[x,1]
  ?mat[x,2]
next

aSort com valor negativo + texto

Enviado: 16 Fev 2015 09:01
por Junior
Bom dia, amigos !

@sambomb
A mehor solução até o momento, boa ideia. Converter os conteúdos em uma string única e depois ordena-la, realmente funcionou com alguns ajustes, veja:

Código: Selecionar todos

Iif(x[2]<0,STRTRAN("A"+STR(ABS(100000+x[2]),12,2)+x[1],".",""), STRTRAN("B"+STR(x[2],12,2)+x[1],".",""))
A lógica é continuar gerando uma string única, aonde os negativos sejam ordenados em prioridade, porém, quanto maior negativo, maior a prioridade, então calculei sobre 100000 o valor negativo e o inverti, ordenando-o pelo resultado encontrato no cálculo. Funcionou mil maravilhas.

@Jairo
Infelizmente não deu certo pois a execução do 2o asort anula o 1o. Ele sempre reposiciona os elementos de acordo com as condições passadas no asort, eliminando a ordenação anterior.

@ANDRIL
Também não funcionou, o asort continuou maluco.

@Eolo
Sua ideia realmente funciona, mas achei um pouco redundante em sua execução. Pra um relatório com cálculos grandes como o que estou processando, acho que não seria viável pela lógica necessária.

A todos, meu agradecimento pela ajuda fornecida. Sei que posso contar com esse fórum sempre que preciso e fico feliz em saber que ele ainda está de pé e tem um futuro imenso pela frente. Pretendo passar mais por aqui pra ajudar no suporte, porém, a correria do dia a dia dita o que consigo fazer e o que não, mas vou me esforçar!

Abraço a todos!
Junior

aSort com valor negativo + texto

Enviado: 16 Fev 2015 11:24
por Eolo
Junior,

Vc não deixou claro que a matriz era muito grande.

Bem, se os dados são muitos, acredito que estão em um DBF. Então, não seria melhor voltar um passo, rever a CRIAÇÃO da matriz?

Com um INDEX adicional no DBF ("str(valor)+curva"), vc já criaria a matriz na ordem desejada, podendo dispensar o uso da ASORT e suas limitações.

Abrss

aSort com valor negativo + texto

Enviado: 16 Fev 2015 12:00
por Junior
Amigo Eolo,

Desculpe-me se me expressei de maneira incorreta, o exemplo passado no primeiro post nada mais é que um exemplo mesmo, bem simples. Não trabalho com DBF, nesse caso em específico preciso gerar um relatório em Excel para o cliente aonde cada grupo de produto é uma sheet, então, com os dados em mãos já devidamente filtrados em SQL, adiciono cada registro em sua array definida, ordenando depois no momento da geração da planilha. Não consigo gerar a planilha se não passar uma array pra cada sheet. O código é utilizado em ADVPL, linguagem de um sistema ERP chamado Microsiga, atualmente mais conhecido como TOTVS.
Assim sendo, se o cliente possui 200 grupos, crio 200 sheets de excel, cada uma com sua array pra não precisar ficar filtrando uma array única por grupo e etc... então, pra eu recalcular a array, removendo valor negativo, adicionando valor positivo, for/next nesses casos iriam comprometer a performance, entende ?

Novamente me desculpe se não fui suficientemente claro.

Abraço!

aSort com valor negativo + texto

Enviado: 16 Fev 2015 12:03
por sambomb
Realmente tinha uma falha no meu código que era que após removido o módulo ele inverteria a ordenação, o menor ao invés de ser -300 ia passar a ser o maior enquanto o maior -100 iria ser o menor.

Mas que bom que minha solução resolveu de ponto inicial para a solução definitiva!

aSort com valor negativo + texto

Enviado: 17 Fev 2015 17:47
por Eolo
com os dados em mãos já devidamente filtrados em SQL
Junior,
Sou zero à esquerda em SQL, a pergunta vai parecer sem nexo, mas aqui vai (pra eu aprender): na filtragem, vc não pode pedir ao SQL pra já ordenar os dados filtrados (por grupo de produto, valor e curva)? Se sim, o uso da ASORT poderia ser inclusive eliminado.
Abrss

aSort com valor negativo + texto

Enviado: 17 Fev 2015 18:47
por Junior
Boa tarde, Eolo!

O cálculo do valor é feito no momento da execução da rotina, ele não existe em base de dados. Primeiro é feio todo um levantamento mensal sobre o que produzir, calculam-se metas, médias, faturamentos, previsões e por ultimo a prioridade é definida, é por ela que o sistema indica o que e quando fabricar. Já ouviu falar na sistemática de Kanban ? É uma técnica japonesa, muitas indústrias utilizam pois ele é um ponto importante no momento de produção, principalmente na orientação do chão de fábrica.

Quanto menor a prioridade(inclusive negativa), maior é a necessidade de fabricar. No Kanban, o menor sempre é maior.

Abraço!

aSort com valor negativo + texto

Enviado: 17 Fev 2015 21:23
por Eolo
Junior,

Há uns tempos ouvi sobre um tal de KanbanFlow, agora o nome eu já sei de onde vem :-)

Eu nunca trabalhei em produção industrial, deve ser algo muito legal. E mais legal ainda é ver um software da gente organizando informações e alimentando um processo do tipo, né não? Parabéns!

Abrss