2

I want to check if there is a value in a certain variable I have. Below I put an example of a logic that I want to achieve.

No matter how hard I tried, I was able to write a very sketchy code as a result of 3 hours of work and research, but it has nothing to do with what I want to achieve.

My Code:

const Files = [
    {
      Name: 'System',
      Type: 'directory',
      Value: [
        {
          Name: 'Main',
          Type: 'directory',
          Value: [
            {
              Name: 'Drivers',
              Type: 'directory',
              Value: [
                {
                  Name: 'Startup',
                  Type: 'file',
                  Value: new FileSystem.File('Startup', 0x1, 'test blah blah'),
                },
              ],
            },
          ],
        },
      ],
    },
  ];

BlahBlah.has(Files, 'System->Main->Drivers');
// [File]
BlahBlah.has(Files, 'System->Main->Drivers->Startup');
// File
BlahBlah.has(Files, 'System->Main->Drivers->AnyWhere');
// undefined
BlahBlah.has(Files, 'System->Main->AnyRandomDirectory');
// NaN

My Function:

function text2Binary(str: string, spliter: string = ' '): string {
  return str
    .split('')
    .map(function (char) {
      return char.charCodeAt(0).toString(2);
    })
    .join(spliter);
}

export function FileTypeFromNumber(e: number) {
  if (typeof e != 'number')
    try {
      e = Number(e);
    } catch (_) {
      return null;
    }

  return {
    0x1: {
      Name: 'Executable File',
      Extension: 'exe',
    },
    0x2: {
      Name: 'Text Document',
      Extension: 'txt',
    },
  }[e];
}

export type FileTypes =
  | 0x1
  | 0x2
  | 0x3
  | 0x4
  | 0x5
  | 0x6
  | 0x7
  | 0x8
  | 0x9
  | null;
export class File {
  Name: string;
  Type: {
    Name: string;
    Extension: string;
  };
  Content: string;
  Size: number;
  constructor(name: string, type: FileTypes, content: string) {
    this.Name = name;
    this.Type = FileTypeFromNumber(type);
    this.Content = content;
    this.Size = text2Binary(content, '').length;
  }
}

export class Directory {
  public Name: string;

  public Files: (File | Directory)[] = [];

  constructor(name: string) {
    this.Name = name;
  }

  addFile(file: File | Directory) {
    this.Files.push(file);
  }

  getFile(name: string): null | (File | Directory)[] {
    if (typeof name != 'string')
      try {
        name = String(name);
      } catch (_) {
        return null;
      }

    const Result = this.Files.filter((e) => e.Name == name);

    return Result.length == 0 ? null : Result;
  }

  getSize() {
    return this.Files.map((e) =>
      e instanceof Directory ? e.getSize() : e.Size
    ).reduce((a, b) => a + b, 0);
  }

  has(name) {
    return this.Files.some((e) => e.Name == name);
  }

  getJSON() {
    return this.Files.map((e) => ({ ...e }));
  }
}
interface x {
  Content: string;
  Name: string;
  Size: number;
  Type: string;
}

export function ConvertFromJSONtoDirectory(json: any[]) {
  return json.map((value) => {
    const isDirectory = value.Type == 'directory';
    if (!isDirectory) {
      return value.Value;
    }
    const self = new Directory(value.Name);
    ConvertFromJSONtoDirectory(value.Value).map((e) => self.addFile(e));
    return self;
  });
}

export default class DirectorySystem {
  Memory: Map<any, any>;
  Current: string | null;

  constructor(Current = null) {
    this.Memory = new Map();
    this.Current = Current;
  }

  addDirectory(directory: Directory): null | true {
    if (!(directory instanceof Directory)) return null;

    if (this.Memory.has(directory.Name)) return null;

    this.Memory.set(directory.Name, directory);
    return true;
  }

  getDirectory(DirectoryName: string): boolean | Directory {
    if (typeof DirectoryName != 'string')
      try {
        DirectoryName = String(DirectoryName);
      } catch (_) {
        return null;
      }

    const Result = this.Memory.has(DirectoryName);

    return Result ? this.Memory.get(DirectoryName) : Result;
  }

  getDirectoryCurrent() {
    if (this.Current == null) return this;
  }

  changeDirectory(by: -1 | 1, value: string) {
    if (by == -1) {
      if (this.Current == null) return null;

      if (this.Current.includes('->')) {
        this.Current = this.Current.split('->').slice(0, -1).join('->');
      } else {
        this.Current = null;
      }

      return this.Current;
    } else if (by == 1) {
      let Position = [this.Current, value].join('->');
      if (this.Current == null) {
        Position = Position.split('->').slice(1).join('->');
      }
      let Result = this.has(Position);
      console.log(Result);
    }
  }

  has(query: string) {
    try {
      return query.split('->').reduce((a, b) => {
        if (Array.isArray(a)) {
          const f = a.filter((e) => e['Name'] == b);
          if (a.length > 0) {
            return f['Files'];
          } else {
            return a;
          }
        }
        return a['Files'];
      }, this.getJSON());
    } catch (_) {
      return false;
    }
  }

  getJSON(): x[][] {
    return [...this.Memory.values()].reduce((a, b) => {
      a[b.Name] = b.getJSON();
      return a;
    }, {});
  }
}

Result: (Thanks Michael M. and chill 389cc for helping me understand the error)

has(
    query: string,
    overwrite = null
  ) {
    // If overwrite argument is not null, we are going use it.
    let files = overwrite == null ? this.getJSON() : overwrite;
    // Split string for getting more usable type with converting string to Array.
    const QueryParams = query.split('->').filter(String);
    // If we dont have no query, we can return current status.
    if (QueryParams.length == 0) return overwrite;
    if (Array.isArray(files)) {
      const SearchFor = QueryParams.shift();
      const Result = files.filter((e) => {
        if (e instanceof Directory) {
          const x = e.Name == SearchFor;
          return x ? e : false;
        }
        return e.Name == SearchFor;
      })[0];
      // If we cant find any indexing result
      if (!Result) return false;
      // We found a file and if we dont have any query this is mean we found it!
      if (Result instanceof File) return QueryParams.length == 0;
      // We found a Directory and we doesnt have any Query now, so we can return true.
      if (Result instanceof Directory && QueryParams.length == 0) return true;
      if (
        Result.Name != SearchFor ||
        (QueryParams.length != 0 && Result.Files.length == 0)
      )
        // If name not suits or still we has Query and not enough file for indexing.
        return false;
      // If nothing happens on upper section, return rescyned version of this function.
      return this.has(QueryParams.join('->'), Result.Files);
    } else {
      // If value is Object, Try Search param in object, and return it.
      const Result = files[QueryParams.shift()];
      return !Result ? false : this.has(QueryParams.join('->'), Result);
    }
  }
6
  • Add your full code. What is the FileSystem class? Is it JS code for web-based environments? Commented Oct 22, 2022 at 16:30
  • I uptated my class file. You can again? Commented Oct 22, 2022 at 16:32
  • Yep, your code worked for me, thank u so much. Commented Oct 22, 2022 at 16:34
  • Yeah, I'm looking for it; but i can't see you post. Commented Oct 22, 2022 at 16:36
  • @Wraithdev2 You should be able to see the post now. Commented Oct 22, 2022 at 16:37

2 Answers 2

1

I can't replicate all of your code, but does this help?

interface Entry {
  Name: string,
  Type: string,
  Value: Array<Entry> | any,
};

const Files = [
  {
    Name: "System",
    Type: "directory",
    Value: [
      {
        Name: "Main",
        Type: "directory",
        Value: [
          {
            Name: "Drivers",
            Type: "directory",
            Value: [
              {
                Name: "Startup",
                Type: "file",
                Value: "test", // change this to anything
              },
            ],
          },
        ],
      },
    ],
  },
];

function getEl(files: Array<Entry>, path: String) {
  let path_walk = path.split("->");

  let obj = files;
  for (let part of path_walk) {
    let found = false;
    for (let entry of obj) {
      if (entry.Name == part) {
        obj = entry.Value;
        found = true;
      }
    }
    if (!found) return undefined;
  }
  return obj;
}

console.log(getEl(Files, "System->Main->Drivers")); // => [ { Name: 'Startup', Type: 'file', Value: 'test' } ]
console.log(getEl(Files, "System->Main->Drivers->Startup")); // => "test"
console.log(getEl(Files, "System->Main->Drivers->AnyWhere")); // => undefined
console.log(getEl(Files, "System->Main->AnyRandomDirectory")); // => undefined
Sign up to request clarification or add additional context in comments.

Comments

1

There are some obvious problems, such as the fact that your example shows .has() being called with two arguments but it is defined in the class to only take in one. That being said, here is a function that, given a string query as you have and an array of objects like you have, would read the query and return if the array works for that query.

function has(fileSystem, query) {
  const arrayOfArgs = query.split('->')
  if (Array.isArray(fileSystem)) {
    for (let i = 0; i < fileSystem.length; i++) {
      if (fileSystem[i]['Name'] === arrayOfArgs[0]) {
        if (arrayOfArgs.length === 1) {
          // element found
          return true; // replace this to return an actual value if that is desired.
        }
        if (fileSystem[i]['Type'] === 'directory') {
          // if not, recurse in if it is a directory
          return has(fileSystem[i]['Value'], arrayOfArgs.slice(1).join('->'));
        } else {
          // if it isn't a directory, don't try to recurse in
          return false;
        }
      }
    }
  }
  return false;
}

console.log(has(Files, 'System->Main->Drivers'));            // true
console.log(has(Files, 'System->Main->Drivers->Startup'));   // true
console.log(has(Files, 'System->Main->Drivers->AnyWhere'));  // false
console.log(has(Files, 'System->Main->AnyRandomDirectory')); // false

You'll have to add your own types to get it back to TypeScript and obviously I pulled it out of the class for easier testing but it should be pretty easy to re-implement.

2 Comments

Thanks, I combined with Michael M's solution; and now function works very good and fast.
@Wraithdev2 great! Not sure why mine is downvoted. It isn't as short as the other solutions but mine should be able to handle if you actually had multiple entries in each array, and do a tad more checking for directories, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.