问题:将项目(T)排序到存储桶(ConcurrentBag)的最佳方法是什么?
好的,所以我还没有参加过算法课程,所以我不确定我遇到的问题的最佳方法。
前提条件:
我目前正通过项目集合上的Parallel.foreach循环使用暴力来使用linq将项目的bucketId与每个桶进行比较。这是非常缓慢和麻烦的,所以我想找到一个更好的方法。
我已经考虑过根据他们的superBucket然后Bucket对项目进行排序,然后遍历每个superbucket->桶来插入项目。这应该是我走的路吗?
感谢您提供的任何帮助。
当前代码示例
ConcurrentBag<Item> items ...
List<SuperBuckets> ListOfSuperBuckets ...
Parallel.ForEach(items, item =>
{
ListOfSuperBuckets
.Where(sBucket => sBucket.id == item.sBucketId)
.First()
.buckets
.Where(bucket => bucket.id == item.bucketId)
.First()
.items
.Add(item);
});
答案 0 :(得分:0)
我不会为此使用并行性,但有很多选项。
var groupedBySBucket = ListOfSuperBuckets
.GroupJoin(items, a => a.id, b => b.sBucketId, (a,b) => new
{
sBucket = a,
buckets = a.buckets
.GroupJoin(b, c => c.id, x => x.bucketId, (c, x) => new
{
bucket = c,
items = x
});
});
foreach (var g in groupedBySBucket)
{
// We benefit here from that the collection types are passed by reference.
foreach (var b in g.buckets)
{
b.bucket.AddRange(b.items);
}
}
或者,如果你的代码太多,这是可以比较的。
var groupedByBucket = ListOfSuperBuckets
.SelectMany(c => c.buckets, (a,b) => new { sBucketId = a.id, bucket = b })
.GroupJoin(items, a => new { a.sBucketId, bucketId = a.bucket.id }, b => new { b.sBucketId, b.bucketId }, (a, b) => new
{
bucket = a.bucket,
items = b
}));
foreach (var g in groupedByBucket)
{
// We benefit here from that the collection types are passed by reference.
g.bucket.AddRange(b.items);
}
这也假设ListOfSuperBuckets
是给定的。如果这只是您实现的工件,那么即使是更简单的方法。这构建了列表。
当然要注意,因为这些是不同的 - 这个没有任何数据的空桶,但第一个实现可以。我们也在创建新的存储桶,第一个实现没有;好的,如果我们需要的话,如果你已经在其他地方创建过它们那么糟糕当然,第一个可以轻松修改以创建它们。
var ListOfSuperBuckets = items
.GroupBy(c => new { c.bucketId, c.sBucketId })
.GroupBy(c => c.Key.sBucketId)
.Select(c => new SuperBucket
{
id = c.Key,
buckets = c.Select(b => new Bucket
{
id = b.Key.bucketId,
items = b.ToList()
}).ToList()
})
.ToList();
对于它的价值,所有这些ToList
电话都是为了保留我认为你拥有的合同。如果您不需要它们,您可以通过将它们关闭而从LINQ的延迟执行中受益。这真的是你如何使用代码的问题,但值得考虑。
答案 1 :(得分:0)
您应该使用Dictionary
,这样您就可以按ID查找存储桶和SuperBuckets,而不是搜索它们。
SuperBucket
应该有一个Dictionary<id_type,Bucket>
可以用来按ID查找存储桶,并且应该将SuperBuckets保持在Dictionary<id_type,SuperBucket>
。 (id_type
是您的ID类型 - 可能是字符串或整数,但我无法从您的代码中说出来)
如果您不想修改现有的类,请构建Dictionary<id_type, Dictionary<id_type, Bucket>>
并使用它。