问题描述
更详细的解释。我需要取一堆数字并将它们放在班级/组中。假设我有 100 个号码。我需要将其除以类数 (n),其中 n = 3,并将它们分为三组,分别为 33、33、34 个数字。或者如果 (n) = 4,那么它将是 25、25、25、25 的 4 个类别。它们也需要保持从最高到最低的分组。
我已经搜索并看到了一些与 LINQ 相关的内容来执行此操作,但我还没有完全了解它。
我想我可以把所有的数字放在一个列表中,然后找到索引中的总数除以类的数量,以找出每个类需要多少。我的问题是如何从列表中提取数字并将它们放在各自的组中,同时保持从高到低的分组。 3 个班级的 15 个数字所需的结果。
List<int> test = new List<int> { 100,99,98,97,96,95,94,93,92,91,90,89,88,87,86 };
int total_indexes = test.Count + 1;
float classes = (total_indexes / 3);
类等于 5,所以它看起来像下面这样
A 类: 100 99 98 97 96
B 类: 95 94 93 92 91
C 类: 90 89 88 87 86
解决方法
这个解决方案可能不是很优化,有可能会改进。
int groupNb = 3,elementNb = 100;
//Populating elements with pseudo-random numbers for demonstration
Random r = new Random();
List<int> elements = new List<int>();
for (int i = 0; i < elementNb; i++)
elements.Add(r.Next(0,100));
//The groups
List<int>[] groups = new List<int>[groupNb];
//Classifying elements in groups
int currentGroup = 0;
foreach (int value in elements.OrderByDescending(x => x))
{
if (groups[currentGroup] == null)
groups[currentGroup] = new List<int>();
groups[currentGroup].Add(value);
currentGroup = ++currentGroup % groupNb;
}
,
好的,所以我写了这段代码来给你你想要的结果:
public List<int[]> Do(int[] numbers,int groupCount)
{
numbers = numbers.OrderByDescending(x => x).ToArray();
var result = new List<int[]>();
var itemsCountInEachGroup = numbers.Length / groupCount;
var remainingCount = numbers.Length % groupCount;
var iterateCount = groupCount;
for (int i = 0; i < iterateCount; i++)
{
var skip = i * itemsCountInEachGroup;
//Last iterate
if (i == iterateCount - 1)
{
var n = numbers.Skip(skip).Take(itemsCountInEachGroup + remainingCount).ToArray();
result.Add(n);
}
else
{
var n = numbers.Skip(skip).Take(itemsCountInEachGroup).ToArray();
result.Add(n);
}
}
return result;
}
示例 =>
var numbers = new[] { 1,2,3,4,5,6,7,8,9,10,11,12,13 };
var res = Do(numbers,5);
,
我是用 PowerShell 回答的 打开 PowerShell ISE 并编写以下脚本:
$Numbers = 100,94,91,90,89,85,84,81,79,74,70,95,92,83
$SortedNumbers = $Numbers | sort -Descending
$NumberofClasses = 3
$Countofnumbersinclase = $Numbers.Count / $NumberofClasses
$x = 0
$y = 0
For ($i = 0 ; $i -lt $NumberofClasses ;$i++){
$y = $i+$Countofnumbersinclase-1+$y
$Clasno = $i+1
Write-host "class No $Clasno is " $SortedNumbers[$X..$Y]
$x = $y+1
}
结果如下:
第 1 类是 100 95 94 92 91 第 2 类是 90 89 85 84 83 第 3 类是 81 79 74 74 70
我认为正是你想要的,你可以添加任何数字或任何类别,它会起作用
,如果所有组(只有最后一个除外)应该具有相同数量的项目,您可以尝试Linq {{1 }} 后跟 OrderBy
:
代码:
GroupBy
如果您的 C# 版本没有 using System.Linq;
...
private static List<T>[] Classify<T>(List<T> source,int count)
where T : IComparable<T> {
int size = source.Count / count;
return source
.OrderBy(item => item)
.Select((item,index) => new { item,index })
.GroupBy(pair => Math.Clamp(pair.index / size,count - 1),pair => pair.item)
.Select(group => group.ToList())
.ToArray();
}
,您可以将其实现为
Math.Clamp
演示:
private static int Clamp(int value,int min,int max) {
return value < min ? min :
value > max ? max :
value;
}
结果:
// Let's split "count" items into "classes" classes
int count = 10;
int classes = 4;
List<int> demo = Enumerable
.Range(1,count)
.ToList();
var result = Classify(demo,classes);
string report = string.Join(Environment.NewLine,result
.Select(list => $"{list.First()} - {list.Last()} ({list.Count} items) : {string.Join(",",list)}"));
Console.Write(report);