https://leetcode.com/discuss/interview-question/369272/Amazon-or-Onsite-or-Linux-Find-Command
https://leetcode.com/discuss/interview-question/609070/Amazon-OOD-Design-Unix-File-Search-API
代码 c++
#include <vector>
#include <string>
#include <stdexcept> // For std::runtime_error
// Definition of the File class
class File {
public:
std::string name;
int size;
int type;
bool isDirectory;
std::vector<File*> children;
};
// Abstract Filter class
class Filter {
public:
virtual bool apply(File* file) = 0; // Pure virtual function
};
// MinSizeFilter class
class MinSizeFilter : public Filter {
int minSize;
public:
MinSizeFilter(int minSize) : minSize(minSize) {}
bool apply(File* file) override {
return file->size > minSize;
}
};
// TypeFilter class
class TypeFilter : public Filter {
int type;
public:
TypeFilter(int type) : type(type) {}
bool apply(File* file) override {
return file->type == type;
}
};
// Follow Up: How would you handle if some contraints should support AND, OR conditionals
// AndFilter class
class AndFilter : public Filter {
std::vector<Filter*> filters; // 存储多个过滤器
public:
AndFilter(const std::vector<Filter*>& filters) : filters(filters) {}
bool apply(File* file) override {
for (auto& filter : filters) {
if (!filter->apply(file)) {
return false; // 如果有一个过滤器不通过,则AND条件失败
}
}
return true; // 所有过滤器都通过
}
};
// OrFilter class
class OrFilter : public Filter {
std::vector<Filter*> filters; // 存储多个过滤器
public:
OrFilter(const std::vector<Filter*>& filters) : filters(filters) {}
bool apply(File* file) override {
for (auto& filter : filters) {
if (filter->apply(file)) {
return true; // 如果有一个过滤器通过,则OR条件成功
}
}
return false; // 所有过滤器都不通过
}
};
// FindCommand class
class FindCommand {
public:
std::vector<File*> findWithFilters(File* directory, std::vector<Filter*> filters) {
if (!directory->isDirectory) {
throw std::runtime_error("NotADirectoryException");
}
std::vector<File*> output;
findWithFilters(directory, filters, output);
return output;
}
private:
void findWithFilters(File* directory, std::vector<Filter*> filters, std::vector<File*>& output) {
if (directory->children.empty()) {
return;
}
for (File* file : directory->children) {
if (file->isDirectory) {
findWithFilters(file, filters, output);
} else {
bool selectFile = true;
for (Filter* filter : filters) {
if (!filter->apply(file)) {
selectFile = false;
break; // No need to check further filters if one fails
}
}
if (selectFile) {
output.push_back(file);
}
}
}
}
};
testCase
// 创建文件和目录结构
File root;
root.isDirectory = true;
root.name = "root";
File file1;
file1.isDirectory = false;
file1.name = "File1";
file1.size = 100;
file1.type = 1; // 假设类型1是文本文件
File file2;
file2.isDirectory = false;
file2.name = "File2";
file2.size = 50;
file2.type = 2; // 假设类型2是图片文件
File dir1;
dir1.isDirectory = true;
dir1.name = "Dir1";
File file3;
file3.isDirectory = false;
file3.name = "File3";
file3.size = 200;
file3.type = 1; // 又一个文本文件
dir1.children.push_back(&file3);
root.children.push_back(&file1);
root.children.push_back(&file2);
root.children.push_back(&dir1);
// 创建最小尺寸过滤器,过滤出大于100字节的文件
MinSizeFilter minSizeFilter(100);
std::vector<Filter*> filters;
filters.push_back(&minSizeFilter);
FindCommand findCommand;
std::vector<File*> results = findCommand.findWithFilters(&root, filters);
std::cout << "Files larger than 100 bytes:" << std::endl;
for (auto& file : results) {
std::cout << file->name << " (" << file->size << " bytes)" << std::endl;
}
// 创建类型过滤器,过滤出类型为1的文件(假设为文本文件)
TypeFilter typeFilter(1);
filters.clear();
filters.push_back(&typeFilter);
results = findCommand.findWithFilters(&root, filters);
std::cout << "Files of type 1:" << std::endl;
for (auto& file : results) {
std::cout << file->name << std::endl;
}
// AND Filter Test
MinSizeFilter minSizeFilter(100);
TypeFilter typeFilter(1);
std::vector<Filter*> andConditions = {&minSizeFilter, &typeFilter};
AndFilter andFilter(andConditions);
std::vector<Filter*> filters;
filters.push_back(&andFilter);
FindCommand findCommand;
std::vector<File*> results = findCommand.findWithFilters(&root, filters);
// OR Filter Test
MinSizeFilter minSizeFilter(100);
TypeFilter typeFilter(1);
std::vector<Filter*> orConditions = {&minSizeFilter, &typeFilter};
OrFilter orFilter(orConditions);
filters.clear();
filters.push_back(&orFilter);
results = findCommand.findWithFilters(&root, filters);