Delete items from a list

From REALbasicWiki

(Redirected from Delete files from a folder)
Jump to: navigation, search
Overall article skill Skill ranges from beginner (green) to expert (red)

Say you have a list of items, be it a true array or an indexed list like FolderItem.TrueItem(idx) or ListBox.List(idx), and you need to scan the list to remove some items from it. You could be tempted to write:

Sub RemoveSomeItems( fromArray() as String )
for idx as integer = 0 to fromArray.Ubound
if ((the condition to remove the item )) then
fromArray.Remove idx
end if
next
End Sub

... and it does not work !!.

Contents

[edit] Why does not it work ?

The problem is that if you remove an item from your array, following items will be moved. Have a look at the following:

We are in a For...Next loop with i as the counter. If you delete Item 2, the following items will be moved but Next has not been executed yet. On execution, it normally increments the counter so i = 3. At this index, you wanted to find Item 3 but you actually get Item 4.

As a summary, you will miss the immediately following item each time you Delete an item.

[edit] Better design proposals

There are many ways to achieve this task properly. Here are some suggestions.

[edit] Adjust the index depending on the removal of an item

If an item gets deleted from an array, the items after it move down index the deletion position. With this understanding, we can keep the index unchanged when an item gets removed from the array:

dim idx as Integer = 0
while idx <= ubound( fromArray ) //Stop at the end of the array
if ((the condition to delete the item )) then
fromArray.Remove idx // If we delete an item, we DO NOT increment the index
else
idx = idx + 1 // Increment the index as we did not remove the item
end if
wend

[edit] Use an array that references the items for deletion

When it comes to deleting files (remember that they are immediately deleted and not put into the trash), which can be referenced by FolderItem objects, one can collect those references, which won't get altered while the items get deleted:

Sub DeleteSomeFiles( fromFolder as FolderItem )
Dim f as FolderItem
Dim filesToDelete() as FolderItem

//We scan the folder and postpone deletion
for idx as integer = 1 to fromFolder.Count
f = fromFolder.TrueItem( idx )
if f <> nil and ((the condition to delete the file )) then
filesToDelete.Append f
end if
next

//Here, you even have the opportunity to ask confirmation from the end-user
MsgBox "The following files will be deleted..."
//...

//Then we actually delete the files
for each f in filesToDelete
f.Delete
next

End Sub

The big difference here is that we store the FolderItem reference in the filesToDelete() array, so we do not even need an explicit counter to delete the file. Storing the index of the files in the array would be a mistake as we would run into the same problems as described above.

See Delete a non-empty folder for a more advanced version of a DeleteFolder function.

[edit] Start from the end

In some cases, you also can just run the loop with the index going backwards:

for idx as integer = ubound( myArray ) downto 0
if ((the condition to delete the item )) then
myArray.Remove idx
end if
Next

[edit] Create a new list

Another way to approach this task is to create a new list. This offers the advantages of faster execution, simpler logic, and easier testability.

dim newList() as String
for i as Integer = 0 to UBound(oldList)
if not ((the condition to delete the item )) then
newList.Append oldList(i)
end if
next

Personal tools
related