Skip to content
Advertisement

How to write a search function to get the path of the desired file?

I have a directory structure that looks like the image. Folder Structure

This structure is organised in a form of objects. File objects are each in the form: {type:'file', name:'file a1'} for example. Folderobjects are like File objects, but they have an extra key children which is an array of sub folders/files.

Here’s a console log of the rootFolder object from the image before:

screenshot of console.log(rootFolder)

The goal: What I want is to write a search function that returns the path for a specific file in the form of an array. For example, if I were to search for file c3, the result would be: ['folder a3', 'folder b4'].

I have tried many things, but recursion isn’t my strongest suit.

The code could be in javascript or python; what I care about is the algorithm itself.

Here is the code used to generate rootFolder:

JavaScript

Advertisement

Answer

remove indrection

Before we get started, first remove the myriad of indirection caused by over 20 variables. We can use just two (2) classes and a single root

JavaScript

remove redundancy

TYPES.FILE and TYPES.FOLDER are unneeded if you have separate File and Folder classes. Each instance will already have an associated type –

JavaScript

multiple return values

Because file systems support folders or files with the same name (at different hierarchies), it’s important that our search algorithm can scan for all possible matches of the query. For a complete example, let’s include file c3 in folder b1 and folder b4. When searching for this file, we expect to see both paths returned –

JavaScript

the algorithm

Now that we’ve fixed the other issues with the code, let’s write search(t, query). We can do this using inductive reasoning

  1. If t is a File and its name matches the query, yield the singleton result [t]
  2. (inductive) t is not a File. If t is a Folder and its name matches the query input the singleton result [t]. And for all child of t.children, for all path of the recursive sub-problem search(child, query), prepend t to the path and yield.
  3. (inductive) t is neither a File nor a Folder. Throw a type error to notify the caller.
JavaScript

Here’s some search examples –

JavaScript
JavaScript
JavaScript
JavaScript

Multiple paths are returned when a file or folder is found multiple times –

JavaScript
JavaScript

When a file or folder cannot be found, no output is given –

JavaScript
JavaScript

caller decides effect

By yielding a sequence of Folder and File objects, our search algorithm remains generic and reusable. Strings are not assembled by default and nothing is logged to the console. If the caller wishes to create a /-separated path, that is demonstrated above. Options for a different effect are left for the caller to decide.

only one result

Using a generator is perfect for search because the caller can choose to consume all matches or any number of them. In this example, we use a generic first to return only the first match. Note the generator is canceled immediately after a match is found and no additional work is done by the cpu –

JavaScript
JavaScript

Make sure you do a proper null-check if using first in this way as it is possible that search yields nothing when no match is found –

JavaScript
JavaScript

higher-order search

In the original algorithm matches are determined using ==. The algorithm could be more useful if we allow the caller to specify what constitutes a match –

JavaScript

Let’s find all files that start with file c

JavaScript
JavaScript

specialization

With a higher-order search function, you can easily implement things like searchByString. This is known as a specialization

JavaScript
JavaScript
JavaScript

code demo

The code above has been condensed so you can see it all in one place. Run the snippet and verify the output –

JavaScript
JavaScript
JavaScript

python

search is written exactly the same in Python –

JavaScript

If you are using Python 3.10, there are some new features available to you. Adjust search to take advantage of the new structural match..case syntax –

JavaScript

Given a tree –

JavaScript

Both implementations behave identically –

JavaScript
JavaScript
JavaScript
JavaScript
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement