面对这里的一个问题,我想我可能已经盯着它看了太久了,我希望有人能给我指明正确的方向。我一直在尝试一些数组操作,我觉得我已经接近了一些方法,但还没有实现。
我想要的是:给定一个值数组(在这个例子中,我将使用简单的值'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));