Ajuda com organização de um array

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

wmanesco
Usuário Nível 3
Usuário Nível 3
Mensagens: 116
Registrado em: 09 Set 2016 13:18
Localização: ITAJAI - SC

Ajuda com organização de um array

Mensagem por wmanesco »

Boa noite pessoal, estou com problema para organizar um array, preciso de ajuda..

é o seguinte, o código serve para uma integração com google drive, a api me retorna um json com uma lista de arquivos.

Preciso organiza-los em array, tipo assim:

Código: Selecionar todos

Pasta
   Sub-Pasta
      Item da Sub Pasta
   Item da Pasta

Montei um exemplo para ver se podem me ajudar, no meu código não está bem assim, mas a é a idéia:

O Array estaria assim:

Código: Selecionar todos

{
   {
	  "id" => "2"
	  "Titulo"	=> "Fotos"
	  "parente" => "1"
   },
   { 
	  "id" => "1"
	  "Titulo" => "Teste"
	  "parente" => "" //ou seja, esta na pasta raiz
   },
   { 
	  "id" => "3"
	  "Titulo" => "teste.jpg"
	  "parente" => "2" //dentro de fotos
   },
   { 
	  "id" => "4"
	  "Titulo" => "doc.pdf"
	  "parente" => "1" //dentro de Teste
   },
   { 
	  "id" => "5"
	  "Titulo" => "documento.docx"
	  "parente" => "" //raiz
   },
   { 
	  "id" => "6"
	  "Titulo" => "desktop.rar"
	  "parente" => "" //raiz
   }
}
Tentei organiza-lo dessa forma, mas tem alguns bugs e não está ficando 100%.

Código: Selecionar todos


   FOR EACH h IN _aFiles
      hFile := hb_Hash()

      hFile["file" ] := h
      hFile["items"] := {}

      AAdd( aFiles, hFile )
   NEXT

   FOR i := Len( aFiles ) TO 1 STEP -1
      hFile := aFiles[i]

      IF !Empty( hFile["file"]["parente"] )
         nPos := AScan( aFiles, { |h| Alltrim( h["file"]["id"] ) == Alltrim( hFile["file"]["parente"] ) } )
         IF !Empty( nPos )
            AAdd( aFiles[ nPos, "items" ], hFile )
            HB_Adel( aFiles, i, .T. )
         ENDIF
      ENDIF
   NEXT

Depois disso, vai ser montado uma TREE com esses itens..

Alguém tem uma idéia para melhorar meu método de ordenação?
William Manesco
Harbour 3.x | Fivewin | BCC | MySQL (TDolphin) | HBQT | HBIDE | Atom
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Ajuda com organização de um array

Mensagem por JoséQuintas »

Eu faria parecido com um menu principal.

Código: Selecionar todos

#define GOOGLE_TITULO 1
#define GOOGLE_ID        2
#define GOOGLE_SUB      3

MenuOption( "Teste", 1 )
   MenuDrop()
   MenuOption(  "Fotos", 2 )
      MenuDrop()
      MenuOption( "teste.jpg", 3 )
      MenuUnDrop()
   MenuOption( "doc.pdf", 4 )
   MenuOption( "Documento.docx", 5 )
   MenuOption( "Desktop.rar", 6 )
   MenuUnDrop()

/*
Array contendo

oMenu := { "titulo", nId, { suboptions }  )
*/
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Ajuda com organização de um array

Mensagem por JoséQuintas »

Apenas como exemplo, um menu principal ilimitado usando esse array, em visual texto, mas estilo W10

Código: Selecionar todos

#include "inkey.ch"

PROCEDURE Main

   LOCAL oMenu

   SetMode( 25, 80 )
   SET EVENTMASK TO INKEY_ALL - INKEY_MOVE
   SetColor( "W/B,N/W,,,W/B" )
   CLS
   oMenu := MenuCria()
   DoMenu( oMenu, .T. )

   RETURN

FUNCTION DoMenu( oMenu, lPrincipal )

   LOCAL oElement, nOpc

   hb_Default( @lPrincipal, .F. )
   DO WHILE .T.
      CLS
      FOR EACH oElement IN oMenu
        @ oElement:__EnumIndex + 2, 10 PROMPT oElement[ 1 ]
      NEXT
      IF lPrincipal
         @ Row() + 1, 10 PROMPT "Sair"
      ELSE
         @ 1, 5 PROMPT "<<<<"
      ENDIF
      MENU TO nOpc

      IF LastKey() == K_ESC .OR. nOpc > Len( oMenu )
         EXIT
      ENDIF
      IF Len( oMenu[ nOpc, 2 ] ) > 0
         DOMenu( oMenu[ nOpc, 2 ] )
      ENDIF
   ENDDO

   RETURN NIL
Dá 600 linhas de fonte só com as opções do menu, então vai em zip pronto pra compilar.
test.zip
(7.67 KiB) Baixado 215 vezes
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
wmanesco
Usuário Nível 3
Usuário Nível 3
Mensagens: 116
Registrado em: 09 Set 2016 13:18
Localização: ITAJAI - SC

Ajuda com organização de um array

Mensagem por wmanesco »

Quintas, obrigado pela resposta.

Esta parte que você me enviou seria mais parecido com a criação da TREE...
Porém a dificuldade está em organiza-lo da forma correta, como está o seu array nesta parte:

No seu caso o array vem certo(por que você que monta), no meu ele vem uma lista apenas indicando seus "parents" e preciso organiza-lo igual está o seu, com um array de itens dentro de outro, para na hora da montagem utilizar recursividade...
JoséQuintas escreveu: /*
17 Array contendo
18
19 oMenu := { "titulo", nId, { suboptions } )
20 */
William Manesco
Harbour 3.x | Fivewin | BCC | MySQL (TDolphin) | HBQT | HBIDE | Atom
wmanesco
Usuário Nível 3
Usuário Nível 3
Mensagens: 116
Registrado em: 09 Set 2016 13:18
Localização: ITAJAI - SC

Ajuda com organização de um array

Mensagem por wmanesco »

Então o que eu preciso seria mais parecido com um "método de organização", ainda estou tentando achar um que funcione, tentei outro assim:

Não deu certo, então não tenho mais o código, mas vou tentar mostrar os passos.

1 - Pegar todas as pastas(arquivos que possuem parents) e colocar em um array.
2 - Organiza-las em seus devidos lugares (dentro da raiz ou dentro de outra pasta)
3 - Correr todos os outros itens (que não são pastas) e ir colocando dentro das pastas.

Era pra funcionar? Por que de repente eu cometi um erro no código e por isso não funcionou..
William Manesco
Harbour 3.x | Fivewin | BCC | MySQL (TDolphin) | HBQT | HBIDE | Atom
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Ajuda com organização de um array

Mensagem por JoséQuintas »

Por isso mantive um elemento pra guardar a ID.
Usando recursividade pode ir colocando cada elemento no seu lugar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Ajuda com organização de um array

Mensagem por alxsts »

Olá!

@William: estou tentando criar uma solução para este problema mas o arquivo JSON postado como exemplo está fora de formato. Poderia postar um arquivo real, no formato correto?
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Ajuda com organização de um array

Mensagem por JoséQuintas »

Código: Selecionar todos

#define OP_ID      1
#define OP_TITULO  2
#define OP_PARENTE 3

PROCEDURE test

   LOCAL aOpcoes

   aOpcoes := { ;
      { "2", "Fotos", "1" }, ;
      { "1", "Teste", ""  }, ;
      { "3", "teste.jpg", "2" }, ;
      { "4", "doc.pdf", "1" }, ;
      { "5", "documento.docx", "" }, ;
      { "6", "desktop.rar", "" } }

   ASort( aOpcoes,,, { | a, b | a[ OP_ID ] < b[ OP_ID ] } )

   Show( aOpcoes, "", 0, "" )

   RETURN

FUNCTION Show( aOpcoes, cParent, nLevel, cPrefixo )

   LOCAL oElement, nOpc := 1

   FOR EACH oElement IN aOpcoes
      IF oElement[ OP_PARENTE ] == cParent
         ? Space( nLevel ) + cPrefixo + Str( nOpc, 1 ) + "." + oElement[ OP_TITULO ]
         Show( aOpcoes, oElement[ OP_ID ], nLevel + 3, cPrefixo + Str( nOpc++, 1 ) + "." )
      ENDIF
   NEXT

   RETURN NIL

Código: Selecionar todos

1.Teste
   1.1.Fotos
      1.1.1.teste.jpg
   1.2.doc.pdf
2.documento.docx
3.desktop.rar
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Ajuda com organização de um array

Mensagem por alxsts »

Olá!

Em meu entendimento, a saída esperada é:

Código: Selecionar todos

> Raiz
     documento.docx
     desktop.rar
     > Teste
         > Fotos
             teste.jpg
         doc.pdf
[]´s
Alexandre Santos (AlxSts)
wmanesco
Usuário Nível 3
Usuário Nível 3
Mensagens: 116
Registrado em: 09 Set 2016 13:18
Localização: ITAJAI - SC

Ajuda com organização de um array

Mensagem por wmanesco »

Obrigado pela ajuda pessoal, consegui resolver.. acontece que o id dos arquivos do google não é do tipo sequencial, então não conseguia dar um asort. Porém achei na documentação da API um filtro OrderBy, e setando ele por data de criação já me ajuda... ai o código para organizar ficou este:

Código: Selecionar todos

/*
   hParents é uma hash, sendo a chave o ID do arquivo PAI(pasta) e o conteudo é um array de arquivos...
   hParents["id"] := {oFile, oFile2, ...}
*/

METHOD organizeFiles() CLASS Drive

   LOCAL aFiles := {}, _aFiles := ::oDriveAPI:getDriveFiles():getFiles()
   LOCAL oFile, hAddedItems := hb_Hash()
   LOCAL hParents

   hParents := ::oDriveAPI:getDriveFiles():getFilesParents()

   FOR EACH oFile IN _aFiles

      IF hb_HHasKey( hAddedItems, oFile:getID() )
         LOOP
      ENDIF

      hFile := hb_Hash()

      hFile["file" ] := oFile
      hFile["items"] := {}

      ::addFilesParents( @hFile, oFile, hParents, @hAddedItems )

      AAdd( aFiles, hFile )
   NEXT

RETURN aFiles

METHOD addFilesParents( hFile, oFile, hParents, hAddedItems ) CLASS Drive

   LOCAL hFileAux, oChild

   IF hb_HHasKey( hParents, Alltrim( oFile:getID() ) )
      FOR EACH oChild IN hParents[ Alltrim( oFile:getID() ) ]
         hFileAux := hb_Hash()

         hAddedItems[ oChild:getID() ] := ""

         hFileAux["file" ] := oChild
         hFileAux["items"] := {}

         ::addFilesParents( @hFileAux, oChild, hParents, @hAddedItems, 2 )

         AAdd( hFile["items"], hFileAux )

      NEXT
   ENDIF

RETURN Self


William Manesco
Harbour 3.x | Fivewin | BCC | MySQL (TDolphin) | HBQT | HBIDE | Atom
Responder