typescript 检查数组层次结构中是否存在值

lf5gs5x2  于 2022-12-24  发布在  TypeScript
关注(0)|答案(2)|浏览(261)

我想检查一下我的某个变量是否有值。下面我举一个我想实现的逻辑的例子。
不管我怎么努力,3个小时的工作和研究的结果是我能够写出一段非常粗略的代码,但这与我想要实现的目标无关。
我的代码:

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

我的职务:

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;
    }, {});
  }
}

结果:(感谢Michael M.和Chill 389cc帮助我理解错误)

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);
    }
  }
hgb9j2n6

hgb9j2n61#

这里有一些明显的问题,比如你的例子显示.has()被两个参数调用,但是它在类中被定义为只接受一个参数。也就是说,这里有一个函数,给定一个字符串查询和一个对象数组,如果数组对该查询有效,它将读取查询并返回。

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

您必须添加自己的类型才能将其返回到TypeScript,显然我将其从类中取出是为了更容易测试,但重新实现它应该非常容易。

2lpgd968

2lpgd9682#

我不能复制你所有的代码,但这有帮助吗?

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

相关问题