我有一个系统用户的列表,这些用户正在等待被分配给帐户。
分配算法非常简单,分配应该尽可能公平,这意味着如果我有40个帐户和20个系统用户,我需要为每个系统用户分配2个帐户。
如果我有41个帐户和20个系统用户,我需要为每个系统用户分配2个帐户,并再次在系统用户之间拆分其余的帐户(在这种情况下,一个系统用户将被分配一个额外的帐户)。
我试图弄清楚如何在使用LINQ查询时做到这一点。
到目前为止,我认为应该进行分组,我的查询如下:
from account in accounts
let accountsPerSystemUser = accounts.Count / systemUsers.Count
let leftover = accounts.Count % systemUsers.Count
from systemUser in systemUsers
group account by systemUser into accountsGroup
select accountsGroup然而,我不知道如何从这里开始。
我肯定我在这里遗漏了where子句,如果您达到分配给系统用户的帐户的最大数量,它将阻止分组。如何正确地实现查询,以便分组知道要分配多少?
发布于 2011-04-14 09:39:05
下面是一个简单的实现,如果您可以将自己限制为IList<T>来实现accounts (但是始终可以使用ToList )。
public static IEnumerable<IGrouping<TBucket, TSource>> DistributeBy<TSource, TBucket>(
this IEnumerable<TSource> source, IList<TBucket> buckets)
{
var tagged = source.Select((item,i) => new {item, tag = i % buckets.Count});
var grouped = from t in tagged
group t.item by buckets[t.tag];
return grouped;
}
// ...
var accountsGrouped = accounts.DistributeBy(systemUsers);基本上,这将获取每个帐户的索引和“标记”,每个索引的剩余整数除以系统用户数。这些标记是它们所属的系统用户的索引。然后,它只是按系统用户在该索引处分组。
这确保了您的公平性要求,因为剩余部分将在0到1之间循环,减去系统用户数。
0 % 20 = 0
1 % 20 = 1
2 % 20 = 2
...
19 % 20 = 19
20 % 20 = 0
21 % 21 = 1
22 % 22 = 2
...
39 % 20 = 19
40 % 20 = 0发布于 2011-04-14 09:43:17
您不能使用“纯LINQ”(即使用查询理解语法)来完成这个任务,老实说,LINQ可能不是这里最好的方法。尽管如此,以下是您如何做到这一点的一个例子:
var listB = new List<string>() { "a", "b", "c", "d", "e" };
var listA = new List<string>() { "1", "2", "3" };
var groupings = (from b in listB.Select((b, i) => new
{
Index = i,
Element = b
})
group b.Element by b.Index % listA.Count).Zip(listA, (bs, a) => new
{
A = a,
Bs = bs
});
foreach (var item in groupings)
{
Console.WriteLine("{0}: {1}", item.A, string.Join(",", item.Bs));
}这一产出如下:
1: a,d
2: b,e
3: chttps://stackoverflow.com/questions/5660819
复制相似问题