multidimensional list?

notedop

Member
Licensed User
Longtime User
Hi,

I've got a piece of code which fills 3 lists with 1. Filename 2. Filetype (directory or not) and 3. file size with the files and directories in a specific path.

Below method works, but does not allow me to sort as then the lists would not be sync'ed anymore.

Is there a way of creating a multidimensional list? I did some research when I had free time at work and found a solution (maybe) with using TYPE and loading these into the lists. However I can not seem to find the post again.
:sign0085:

B4X:
filetype.initialize
filesize.initialize
filelist.initialize

filelist= File.listfiles(Path)

If filelist.IsInitialized Then
   For i =0 To filelist.Size-1
      If File.IsDirectory(Path, filelist.Get(i)) Then
         filetype.Add("Directory")
         Else
         filetype.Add("Other")
      End If

      filesize.Add(File.Size(Path, filelist.Get(i)))
   Next
Else
   If Path.EndsWith("/") AND Path.Length <> 1 Then
      Path2 = Path2.SubString2(0,Path2.Length-1)
      Path2 = Path2.SubString2(0,Path2.LastIndexOf2("/", Path2.Length))
      If Path2 = "" Then Path2= "/"
      ToastMessageShow("Error: back", False)
      listfoldercontent(Path2)
   Else 
      Path2 = "/"
   End If
End If
 

notedop

Member
Licensed User
Longtime User
Thanks, I'll check out the code tonight. However I'll first have to check how to actually use the TYPE declaration.

I think I found a simple example here

I'll post some code as soon as I have it working, or not working and need help ;)
 
Upvote 0

notedop

Member
Licensed User
Longtime User
Allright, first part is working. Now I know how to use the TYPE declaration, rather easy :

B4X:
Sub Process_Globals
Type files(Fid As Int, Fname As String, Ftype As String, Fsize As Int)

Now the sub: (uses mimetype library)

B4X:
Sub listfoldercontent2(Path As String)   

Dim explore As files
Dim EXTType As MimeType

Dim filelist2 As List


filelist.initialize
filelist2.Initialize

filelist= File.listfiles(Path)

If filelist.IsInitialized Then
   For i =0 To filelist.Size-1
      explore.Fid = i
      explore.Fname = filelist.Get(i)
      explore.Fsize = File.Size(Path, filelist.Get(i))
      If EXTType.getFileExtensionFromUrl(Path & "/" & filelist.get(i)) <> "" Then
         explore.Ftype = EXTType.getFileExtensionFromUrl(Path & "/" & filelist.get(i))
      Else If File.IsDirectory(Path, filelist.Get(i)) Then
         explore.Ftype = "DIR"
      Else
         explore.Ftype = "Unknown"
      End If
      Log("ID " & explore.Fid)
      Log("Name " & explore.Fname)
      Log("Type " & explore.Ftype)
      Log("Size " & explore.Fsize )
      filelist2.Add(explore)
   Next
Else
   If Path.EndsWith("/") AND Path.Length <> 1 Then
      Path2 = Path2.SubString2(0,Path2.Length-1)
      Path2 = Path2.SubString2(0,Path2.LastIndexOf2("/", Path2.Length))
      If Path2 = "" Then Path2= "/"
      ToastMessageShow("Error: back", False)
      listfoldercontent2(Path2)
   Else 
      Path2 = "/"
   End If
End If

End Sub

This gives the following log:

B4X:
LogCat connected to: emulator-5554
** Activity (main) Create, isFirst = true **
5
** Activity (main) Resume **
ID 0
Name dev
Type DIR
Size 0
ID 1
Name root
Type DIR
Size 0
ID 2
Name data
Type DIR
Size 0
ID 3
Name default.prop
Type prop
Size 118
ID 4
Name init
Type Unknown
Size 107412
ID 5
Name init.goldfish.rc
Type rc
Size 1677
ID 6
Name init.rc
Type rc
Size 12995
ID 7
Name proc
Type DIR
Size 0
Etc etc etc etc

Still have to look into on how to sort this list on a specified field like Name, Size or Type or even better, a combination of all.
Looking at your example Erel uses a MAP type, haven't used that so I guess Ill have to read alittle bit about it.

:sign0089:
 
Upvote 0

notedop

Member
Licensed User
Longtime User
Well it seems that I have an error in my previously posted code.
Appearantly the list is not correctly being filled with the declared TYPE value explore.
It does add the TYPE object Explore to the filelist2, but at the end of the sub all values contain the last value of type.
Solution is moving the Dim explore as Files at the beginning of the For ... Next loop.
 
Upvote 0

notedop

Member
Licensed User
Longtime User
Hahahahaha, you know. I have the code working including the sorting stuff. And you know what the funny part is, after I finished I noticed that LIST property already has a function to sort the list on a specified type. for instance:

list.sorttype("fname", true)

well, anyhow, heres the sub I wrote using the example.
But I don''t think I will be using below. I'll just use the build in function and then create a seperate sub which sorts directorys and files seperatly and then combines them again to a new list. This way I can make sure that directorys are always listed first, or last.

B4X:
Sub sortlist(list2sort As List, SortOn As String, direction As Boolean) As List

Dim m As Map
m.Initialize

Dim list2 As List        
list2.Initialize


Select SortOn
Case "fname"
   For i =0 To list2sort.Size-1
      Dim f As files
      f = list2sort.Get(i)
      m.Put(f.Fname, f)            'The name is what we want to sort on, so this is the key
   Next

'The type is what we want to sort on, so this is the key. Add the int number
'to create a uniek key value. Needed as you can have multiple files of the same
'type in a directory.
Case "ftype"
   For i =0 To list2sort.Size-1
      Dim f As files
      f = list2sort.Get(i)
      m.Put(f.Ftype & i, f)            
   Next                           

Case "fsize"
   For i =0 To list2sort.Size-1
      Dim f As files
      f = list2sort.Get(i)
      m.Put(f.fsize & i, f)            
   Next      
End Select

'now write the keyvalues to a bufferlist

For i =0 To m.Size-1
   list2.Add(m.GetKeyAt(i))
Next

'as We are sorting on keyvalues, we can just sort the list easily using the specified direction.

list2.Sort(direction)
list2sort.Clear

'now lookup the sorted value one by one from the list in the map which holds the fully declared type.
For i = 0 To m.Size-1
   Dim s As String
   s = list2.Get(i)
   Dim a As files
   a = m.Get(s)
   list2sort.add(a)
Next

'and return the full list.
Return list2sort


End Sub
 
Upvote 0

notedop

Member
Licensed User
Longtime User
wrote the following code at work in notepad2. Have not tested it yet but it should work.


B4X:
'list2sort is the list containing all directorys and files in a specific path. The data is hold in a TYPE declarion called Files
'Direction true is for ascending, false is for descending
'direction2 is true for showing directory's first in the final list, false for first showing the files
'SortOn string is the type you would like to sort on. For this type you can use, Ftype, Fname, Fsize
sub sortlist(list2sort as list, direction as boolean, direction2 as boolean,SortOn as string) as list

dim dirlist as list
dim filelist as list

'split the list into to files and directories
for i=0 to list2sort.size-1
  dim f as files
  f = list2sort.get(i)

    select f.ftype
      case "dir"
        dirlist.add(f)
      case else
        filelist.add(f)
    end select
 next
 
 'sort both lists using the specified direction
 dirlist.sorttype(SortOn, direction)
 filelist.sorttype(sortOn, direction)

' Based on direction2 show files or directory's first. True for directory first, false for files first
select direction2
  case true
    'first insert the directories into the list2sort list
    for i=0 to dirlist.size-1
      dim f as files
      f=dirlist.get(i)
      list2sort.InsertAt(i, f)
    next
    'now insert the files into the list2sort list
    for i=0 to filelist.size-1
      dim f as files
      f=filelist.get(i)
      list2sort.insertat(i+(dirlist.size-1), F) 'add the dirlist size to get the next position to write on. Else you would overwrite previous data
     next
     
  case false
    'First insert the files into the list2sort list
    for i=0 to filelist.size-1
      dim f as files
      f=filelist.get(i)
      list2sort.insertat(i, F)
     next
     'now insert the directories into to list2sort list
    for i=0 to dirlist.size-1
      dim f as files
      f=dirlist.get(i)
      list2sort.InsertAt(i+(filelist.size-1), f)
    next
end select

'return the sorted list
return list2sort

end sub
 
Upvote 0
Top