如何根据可变的所需金额(C#)对多组值进行分组



面对这里的一个问题,我想我可能已经盯着它看了太久了,我希望有人能给我指明正确的方向。我一直在尝试一些数组操作,我觉得我已经接近了一些方法,但还没有实现。

我想要的是:给定一个值数组(在这个例子中,我将使用简单的值'A', 'B', 'C', 'D'),以及每个值所需的最小出现次数,能够将这些值的集合按所需大小分组。例如:

// when given this list of required amounts
var config = new[] {
{ Value: 'A', AmountRequired: 1 },
{ Value: 'B', AmountRequired: 2 },
{ Value: 'C', AmountRequired: 3 },
{ Value: 'D', AmountRequired: 4 }
};
// and this array of values (matches requirements exactly)
var values = new[] { 'A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D' };
// the logic would return
var results = [
['A'],
['B', 'B'],
['C', 'C', 'C'],
['D', 'D', 'D', 'D'],
];

// this array of values (with one extra of each value) would also return the same result
// because there aren't enough added values for a second combined group
var values = new[] { 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'D' };

最容易描述行为的用例可能就像一个电子游戏制作菜单,在那里你会看到类似";你需要1个A,2个B,3个C和4个D才能制作这个项目";,所以你感兴趣的只是你有多少完整的这些值,任何备件都可以忽略。

我曾使用Linq尝试过这一点,当所有字段所需的数量都相同时,我就让它工作了,这显然不能满足所有的用例。我不打算在这里发布我的代码尝试,因为我希望对这个问题有一个新的看法,但如果有帮助的话,我可以提供它。

提前感谢

标记

这个答案是基于这样的假设,即结果可以简单地是一个完整集合的计数。


我建议从创建源数组内容的概述开始:每个字符出现多少次?字典是一个很好的概括工具。

首先,需要对源数组中的值进行分组。然后,可以基于这些组创建字典。每个KeyValuePair的关键字是char,值是该char的出现次数:

var countPerChar = values
.GroupBy(_ => _)
.ToDictionary(
charGroup => charGroup.Key,
charGroup => charGroup.Count());

如果你的源阵列是这样的:

var values = new[] { 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'D' };

,则countPerChar将看起来像这样:

然后,我将创建一个字典来存储每个字符的全集的计数。这个字典应该包含与config一样多的条目(并且config中的所有键都应该存在(。

对于config中的每个条目,我都会尝试从countPerChar中获取目标char的值。

如果countPerChar中存在目标字符,则可以将相关的字符计数除以所需的数量,以获得目标字符的全集

如果countPerChar中不存在的目标字符,则目标字符全集为0

var completeSetsPerChar = new Dictionary<char, int>();
foreach (var entry in config.Where(c => c.AmountRequired > 0))
{
countPerChar.TryGetValue(entry.Value, out int charCount);

completeSetsPerChar[entry.Value] = charCount / entry.AmountRequired;
}

现在,要获得全集的计数,只需取每个字符的所有完备集的最小值

var completeSets = completeSetsPerChar.Values.Min();

小提琴的例子。

我还有一个解决方案,可以告诉你一个集合是否完整:

// when given this list of required amounts
var config = new[] {
new { Value= 'A', AmountRequired= 1 },
new { Value = 'B', AmountRequired= 2 },
new { Value = 'C', AmountRequired = 3 },
new { Value= 'D', AmountRequired= 4 }
};
// and this array of values (matches requirements exactly)
var values = new[] { 'A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D' };
var res =
from cfg in config
select (new { cfg.Value, setComplete = (values.Count(x => x == cfg.Value) >= cfg.AmountRequired) });
res.ToList().ForEach(x => Console.WriteLine(x));

最新更新