c# - 使用 LINQ 对结果 "fairly"进行分组

标签 c# .net linq

我有一份系统用户的列表,这些用户正在等待分配一个帐户
分配算法非常简单,分配应该尽可能公平,这意味着如果我有 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 子句,如果您达到要分配给系统用户的最大帐户数量,它将阻止分组。 如何正确实现查询,以便分组知道要分配多少?

最佳答案

这是一个简单的实现,如果您可以将自己限制在 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

关于c# - 使用 LINQ 对结果 "fairly"进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5660819/

相关文章:

c# - 验证策略

c# - 从 csproj 文件中读取引用列表

c# - 如何使用纬度和经度计算距离和方位?

c# - .NET DataGridView 显示对象字段

c# - 结构图 IContainer 实现

c# - LINQ 中 AsEnumerable() 的内部实现

c# - 单个与多个 MemoryCache 实例

.net - MVVM应用程序序列化设计/实现的示例

c# - Like 不会转义特殊字符 NHibernate

c# - Linq 语句中的 TSource 有什么意义?