Вы на правильном пути: если вы хотите использовать шаблоны fnmatch
-типов, вы должны использовать fnmatch.filter
.
Но есть три проблемы, которые делают это не совсем тривиальным.
Во-первых, вы хотите применить несколько фильтров. Как ты это делаешь? Вызов filter
несколько раз:
for ignore in ignore_files:
filenames = fnmatch.filter(filenames, ignore)
Во-вторых, вы действительно хотите сделать reverse из filter
: вернуть подмножество имен, которые не . Как объясняет документация:
Это то же самое, что и
blockquote>[n for n in names if fnmatch(n, pattern)]
, но реализовано более эффективно.Итак, чтобы сделать наоборот, вы просто бросаете в
not
:for ignore in ignore_files: filenames = [n for n in filenames if not fnmatch(n, ignore)]
Наконец, вы пытаетесь фильтровать частичные имена путей, а не только имена файлов, но вы не выполняете
join
до тех пор, пока не будет фильтрация. Итак, переключите порядок:filenames = [os.path.join(root, filename) for filename in filenames] for ignore in ignore_files: filenames = [n for n in filenames if not fnmatch(n, ignore)] matches.extend(filenames)
Есть несколько способов улучшить это.
Вы можете использовать выражение генератора вместо понимания списка (вместо скобок квадратных скобок), поэтому, если у вас есть огромные списки имен файлов, вы используете ленивый конвейер вместо того, чтобы тратить время и пространство на многократное построение огромных списков.
Кроме того, может быть и не проще понять, если вы инвертируете порядок циклов, например:
filenames = (n for n in filenames if not any(fnmatch(n, ignore) for ignore in ignore_files))
Наконец, если вас беспокоит производительность, вы можете использовать
fnmatch.translate
для каждого выражения, чтобы превратить их в эквивалентные регулярные выражения, а затем объединить их в одно большое регулярное выражение и скомпилировать его, и использовать это вместо цикла вокругfnmatch
. Это может оказаться сложным, если ваши шаблоны могут быть более сложными, чем просто*.jpg
, и я бы не рекомендовал его, если вы действительно не определяете узкое место производительности здесь. Но если вам нужно это сделать, я видел, по крайней мере, один вопрос о SO, где кто-то приложил много усилий, чтобы выбить все крайние случаи, поэтому поиск вместо того, чтобы пытаться написать его самостоятельно.
Это хорошая модель?
Это мои классы:
public class Suace
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
public class Pizza
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public ICollection<Idgredient> Idgredients { get; set; }
public Sauce Sauce {get;set;}
public virtual ICollection<Order> Orders { get; set; }
}
class Order
{
public Order()
{
Cars = new List<Car>();
Parts = new List<Part>();
}
public int OrderId { get; set; }
public virtual ICollection<Car> Suace { get; set; }
public virtual ICollection<Part> Pizza { get; set; }
}
public class Idgredient
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Pizza> Pizzas { get; set; }
}
Давайте начнем с физических таблиц, которые вам понадобятся:
Part { Id, Name, Price }
Car { Id, Name, Price }
Order { Id }
OrderPart* { OrderId, PartId }
OrderCar* { OrderId, CarId }
Последние две таблицы называются «таблицами соединения», потому что они нужны для того, чтобы иметь возможность хранить несколько деталей и несколько автомобилей в одном порядке. , но на самом деле это не таблицы, которые вы считаете частью своей модели.
Entity Framework автоматически создаст эти таблицы соединений, если вы настроите ваши классы следующим образом:
public class Car
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
public class Part
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
class Order
{
public Order()
{
Cars = new List<Car>();
Parts = new List<Part>();
}
public int OrderId { get; set; }
public virtual ICollection<Car> Cars { get; set; }
public virtual ICollection<Part> Parts { get; set; }
}
Обратите внимание, что свойства ICollection <> таблицы Car и Part будут подсказкой EF, что она Нужно сделать таблицу соединений. Кроме того, помните, что вам нужно "виртуальный" в ваших свойствах навигации.