查询时Shuffle产品列表
本文关键字:产品列表 Shuffle 查询 | 更新日期: 2023-09-27 18:10:55
我在数据库中有一个产品和类别表:
Products有以下几列:ProductId, ProductName, Description, Path, Name, URL, CategoryId, Active
Category有以下列:被标记,CategoryName
我写了一个LINQ语句来查询数据库并获取相关类别的产品。查询工作正常。
public IQueryable<Product> GetProducts(
[QueryString("id")] int? categoryId,
[RouteData] string categoryName)
{
var _db = new products.Models.ProductContext();
IQueryable<Product> query = _db.Products;
if (categoryId.HasValue && categoryId > 0)
{
query = query.Where(p => p.CategoryID == categoryId);
}
if (!String.IsNullOrEmpty(categoryName))
{
query = query.Where(p =>
String.Compare(p.Category.CategoryName,
categoryName) == 0);
}
return query;
}
我有两个疑问:
如何修改此查询以只选择Active = 1的产品
当前查询以特定顺序返回行,我认为基于productId - 1,2,3,4,5等。如何对结果进行洗牌,使结果不按特定顺序返回?它可以是5、2、4、1、3,或者下一次运行时是3、5、1、4、2等等。
首先是洗牌部分。这在IQueryable
中是做不到的,所以最好在一些常见的地方引入一个通用的扩展方法:
public static void Swap<T>(ref T x, ref T y)
{
var temp = x;
x = y;
y = temp;
}
public static T[] RandomShuffle<T>(this IEnumerable<T> source)
{
var result = source.ToArray();
if (result.Length < 2) return result;
var random = new Random();
for (int i = result.Length - 1; i > 0; i--)
{
int pos = random.Next(i + 1);
if (pos != i) Swap(ref result[pos], ref result[i]);
}
return result;
}
现在你的函数:
public IQueryable<Product> GetProducts(
[QueryString("id")] int? categoryId,
[RouteData] string categoryName)
{
var _db = new products.Models.ProductContext();
IQueryable<Product> query = _db.Products;
query = query.Where(p => p.Active == 1); // the first question
if (categoryId.HasValue && categoryId > 0)
{
query = query.Where(p => p.CategoryID == categoryId);
}
if (!String.IsNullOrEmpty(categoryName))
{
query = query.Where(p =>
String.Compare(p.Category.CategoryName,
categoryName) == 0);
}
return query;
}
你可以保持这种方式(在我看来更好),当你需要这种行为时,在调用端应用shuffle,比如GetProducts(....).RandomShuffle()
。或者,如果你坚持在里面做,就把最后一行改成return query.RandomShuffle().AsQueryable();
要筛选Active产品,只需按以下方式扩展查询:
query = query.Where(p => p.CategoryID == categoryId && p.Active == 1);
要变换结果,您必须自己编写一些代码。它可能是这样的:
var shuffledList = new List<Product>();
var originalList = query.ToList();
var random = new Random();
while (originalList.Count() > 0) {
var pick = random.Next(0, originalList.Count());
var product = originalList[pick];
shuffledList.Add(product);
originalList.Remove(product);
}
shuffledList
将以随机顺序包含您的产品。你会有一些内存负载,因为你有两倍的产品在你的内存。
我刚刚遇到的另一种可能是:
var random = new Random();
query = query.OrderBy(product => random.Next());