Página 1 de 1

Ajuda com organização de um array

Enviado: 24 Dez 2016 21:20
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?

Ajuda com organização de um array

Enviado: 25 Dez 2016 10:34
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 }  )
*/

Ajuda com organização de um array

Enviado: 25 Dez 2016 10:41
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 214 vezes

Ajuda com organização de um array

Enviado: 25 Dez 2016 13:23
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 */

Ajuda com organização de um array

Enviado: 25 Dez 2016 13:26
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..

Ajuda com organização de um array

Enviado: 25 Dez 2016 17:57
por JoséQuintas
Por isso mantive um elemento pra guardar a ID.
Usando recursividade pode ir colocando cada elemento no seu lugar.

Ajuda com organização de um array

Enviado: 27 Dez 2016 14:55
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?

Ajuda com organização de um array

Enviado: 27 Dez 2016 15:39
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

Ajuda com organização de um array

Enviado: 27 Dez 2016 16:53
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

Ajuda com organização de um array

Enviado: 27 Dez 2016 18:58
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