首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用LINQ对结果进行“公平”分组

使用LINQ对结果进行“公平”分组
EN

Stack Overflow用户
提问于 2011-04-14 09:02:29
回答 2查看 111关注 0票数 1

我有一个系统用户的列表,这些用户正在等待被分配给帐户

分配算法非常简单,分配应该尽可能公平,这意味着如果我有40个帐户和20个系统用户,我需要为每个系统用户分配2个帐户。

如果我有41个帐户和20个系统用户,我需要为每个系统用户分配2个帐户,并再次在系统用户之间拆分其余的帐户(在这种情况下,一个系统用户将被分配一个额外的帐户)。

我试图弄清楚如何在使用LINQ查询时做到这一点。

到目前为止,我认为应该进行分组,我的查询如下:

代码语言:javascript
复制
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子句,如果您达到分配给系统用户的帐户的最大数量,它将阻止分组。如何正确地实现查询,以便分组知道要分配多少?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-14 09:39:05

下面是一个简单的实现,如果您可以将自己限制为IList<T>来实现accounts (但是始终可以使用ToList )。

代码语言:javascript
复制
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之间循环,减去系统用户数。

代码语言:javascript
复制
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
票数 2
EN

Stack Overflow用户

发布于 2011-04-14 09:43:17

您不能使用“纯LINQ”(即使用查询理解语法)来完成这个任务,老实说,LINQ可能不是这里最好的方法。尽管如此,以下是您如何做到这一点的一个例子:

代码语言:javascript
复制
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));
}

这一产出如下:

代码语言:javascript
复制
1: a,d
2: b,e
3: c
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5660819

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档