C# 爆炸清单<;T>;分组
我有一个扩展,可以将列表分解为多个组,这使得显示内容变得简单。这是分机码C# 爆炸清单<;T>;分组,c#,asp.net-mvc,C#,Asp.net Mvc,我有一个扩展,可以将列表分解为多个组,这使得显示内容变得简单。这是分机码 public static List<List<T>> GroupItems<T>(this List<T> items, int totalGroups) { List<List<T>> groups = null; if (items != null) { groups = new List<List&
public static List<List<T>> GroupItems<T>(this List<T> items, int totalGroups)
{
List<List<T>> groups = null;
if (items != null)
{
groups = new List<List<T>>();
int itemsPerGroup = (int)Math.Ceiling((double)items.Count / totalGroups);
if (itemsPerGroup > items.Count)
{
List<T> group = new List<T>(items);
groups.Add(group);
}
else
{
for (int i = 0; i < totalGroups; i++)
{
List<T> group = items.Skip(i * itemsPerGroup).Take(itemsPerGroup).ToList();
groups.Add(group);
}
}
}
return groups;
}
现在这是错误的,理想情况下我应该
- 第1组:4个项目
- 第2组:3个项目
- 第3组:3个项目
- 第4组:3个项目
- 第1组:3个项目
- 第2组:3个项目
- 第3组:3个项目
- 第4组:3个项目
- 第5组:1个项目
- 第6组:0项
- 第1组:3个项目
- 第2组:2个项目
- 第3组:2个项目
- 第4组:2个项目
- 第5组:2个项目
- 第6组:2个项目
我错过了什么?如何解决此问题?每次我都会计算每组的项目数
int itemsPerGroupCount = 0;
for (int i = 0; i < totalGroups; i++)
{
int itemsPerGroup = (int)Math.Ceiling(
((double)items.Count - itemsPerGroupCount) / (totalGroups - i));
itemsPerGroupCount += itemsPerGroup;
List<T> group = items.Skip(itemsPerGroupCount).Take(itemsPerGroup).ToList();
groups.Add(group);
}
int itemsPerGroupCount=0;
对于(int i=0;i
我会计算每组的物品(地板而不是天花板):
然后我会计算出剩余项目的数量:
int remainingItems = items.Count % totalGroups
然后在你的循环中:
int itemsToSkip = 0;
for (int i = 0; i < totalGroups; i++)
{
int itemsPerGroupTemp = itemsPerGroup;
if (remainingItems != 0) {
itemsPerGroupTemp++;
remainingitems--;
}
List<T> group = items.Skip(itemsToSkip ).Take(itemsPerGroupTemp).ToList();
groups.Add(group);
itemsToSkip += itemsPerGroupTemp;
}
int itemsToSkip=0;
对于(int i=0;i
换一种方式怎么样,
假设你有13件物品想要6组
所以取(int)(13/6)并将其落地,这将给你2。现在用相同的组数(6)乘以组大小(2)得到12。你有13个项目,所以你有一个剩余,添加到第一组。应该为您提供一组组组。如果您将for循环调整为类似的内容
for (int i = 0; i < totalGroups; i++)
{
List<T> group = items.Skip(i * itemsPerGroup).Take(itemsPerGroup).ToList();
groups.Add(group);
if(i==0)
itemsPerGroup = (int)Math.Ceiling((double)(items.Count - itemsPerGroup )/ (totalGroups - 1) );
}
var result = list.Select((v,i)=>new{Value=v,Index=i})
.GroupBy(x => x.Index % numberOfGroups)
.Select(grp => grp.Select(x => x.Value).ToList())
.ToList();
for(int i=0;i
因为你想要每组的平均值和最早的四舍五入值,只要需要,我可以推荐这种算法
public static List<List<T>> GroupItems<T>(this List<T> items, int totalGroups)
{
if (items == null || totalGroups == 0) return null;
var ret = new List<List<T>>();
var avg = items.Count / totalGroups; //int rounds towards 0
var extras = items.Count - (avg * totalGroups);
for (var i = 0; i < totalGroups; ++i)
ret.Add(items.Skip((avg * i) + (i < extras ? i : extras)).Take(avg + (i >= extras ? 0 : 1)).ToList());
return ret;
}
publicstaticlist-GroupItems(此列表项,int-totalGroups)
{
如果(items==null | | totalGroups==0)返回null;
var ret=新列表();
var avg=items.Count/totalGroups;//整数向0舍入
var extras=项目数-(平均*总组);
对于(变量i=0;i=extras?0:1)).ToList();
返回ret;
}
它的优点是,它很短,可以考虑,并且可以像任何二维算法一样用O(n^2)进行缩放。设计思想是:找到平均值,在平均值之后找到N=缺少的元素,让前N个元素得到一个额外的元素来填补空白。如果组中项目的顺序不相关,那么您可以通过按组数的索引对Linq进行分组来简单地做到这一点
var result = list.Select((v,i)=>new{Value=v,Index=i})
.GroupBy(x => x.Index % numberOfGroups)
.Select(grp => grp.Select(x => x.Value).ToList())
.ToList();
那么下面
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
var result =
list.Select((v, i) => new { Value = v, Index = i })
.GroupBy(x => x.Index % 6)
.Select(grp => grp.Select(x => x.Value).ToList())
.ToList();
int groupNumber = 1;
foreach (var l in result)
{
Console.WriteLine("Group {0} : {1}", groupNumber++, string.Join(", ", l));
}
List List=新列表{1,2,3,4,5,6,7,8,9,10,11,12,13};
var结果=
list.Select((v,i)=>new{Value=v,Index=i})
.GroupBy(x=>x.索引%6)
.Select(grp=>grp.Select(x=>x.Value).ToList())
.ToList();
int groupNumber=1;
foreach(结果中的var l)
{
WriteLine(“组{0}:{1}”,groupNumber++,string.Join(“,”,l));
}
将产生这些结果
第一组:1,7,13
第2组:2,8
第3组:3,9
第4组:4,10
第5组:5,11
第6组:6,12
我想您应该做的是计算每个bucket的平均项目数量(也称为List),然后将该数量插入每个bucket,然后插入剩余的对象 注意:保持秩序,
可以替换为
例如:
public static List<List<int>> ExpandIntoGroups(this List<int> items, int totalGroups)
{
List<List<int>> expandedList = null;
if (items != null)
{
expandedList = new List<List<int>>();
// Get amount of items to insert per list (for example: for 14 items, 4 groups, returns {4, 4, 3, 3}
int[] itemsToInsertPerGroup = GetItemsToInsertPerGroup(items, totalGroups);
// Go over each group
for (int currGroup = 0, itemCount = 0;
currGroup < itemsToInsertPerGroup.Length;
currGroup++)
{
// add the list for the group
expandedList.Add(new List<int>());
// Add as much items as needed
for (int i = 0;
i < itemsToInsertPerGroup[currGroup] &&
itemCount < items.Count;
i++, itemCount++)
{
expandedList[currGroup].Add(items[itemCount]);
}
}
}
return expandedList;
}
private static int[] GetItemsToInsertPerGroup(List<int> items, int totalGroups)
{
// Get average amount of items per list
int avgItemsPerGroup = (int)(items.Count / totalGroups);
int[] itemsToInsert = new int[totalGroups];
// Set each cell to be the average
for (int i = 0; i < itemsToInsert.Length; i++)
{
itemsToInsert[i] = avgItemsPerGroup;
}
// get how many items remain after inserting average amount
int remainingItems = items.Count - avgItemsPerGroup * totalGroups;
// Increase the amount needed per cell for each remaining item
for (int i = 0, j = 0;
i < remainingItems;
++i, ++j)
{
itemsToInsert[j]++;
}
return itemsToInsert;
}
问题是,在移动到下一个铲斗之前,要先将每个铲斗装满。您似乎希望在所有存储桶中均匀分布。
int itemsPerGroup=(int)Math.天花((double)items.Count/totalGroups)代码>基本上我的方法是错误的。。有什么建议可以让它变得更好吗?请用注释检查这个答案,因为这是一个没有什么有趣的算法问题,有简单的解决方案,我建议你自己去做(即使这需要更多的时间)。正如你的名字表明你正在学习编程一样,寻求帮助并不坏,但在这种情况下,我建议你更努力一点,自己解决它……小组中项目的顺序重要吗?也就是说,前x个项目必须在第一组,或者你能把前x个项目分为不同的组吗?我有4组,4+3+3+3,这是正确的。但是,第1组第4项和第2组第1项是相同的。@learning。。。是的,看起来跳过部分有问题。订单与此非常相关。我已经测试了你的建议,如果我给我4组4+3+3项。然而,第1组第4项和第2组第1项是相同的。在这里的所有解决方案中,这起到了保持项目完整的作用。现在,即使我分成4组,我得到的第五组有0个项目。我将在这里选择你的解决方案作为答案。我已删除插入此处的空项。我已经用其他的s测试过了
public static List<List<int>> ExpandIntoGroups(this List<int> items, int totalGroups)
{
List<List<int>> expandedList = null;
if (items != null)
{
expandedList = new List<List<int>>();
// Get amount of items to insert per list (for example: for 14 items, 4 groups, returns {4, 4, 3, 3}
int[] itemsToInsertPerGroup = GetItemsToInsertPerGroup(items, totalGroups);
// Go over each group
for (int currGroup = 0, itemCount = 0;
currGroup < itemsToInsertPerGroup.Length;
currGroup++)
{
// add the list for the group
expandedList.Add(new List<int>());
// Add as much items as needed
for (int i = 0;
i < itemsToInsertPerGroup[currGroup] &&
itemCount < items.Count;
i++, itemCount++)
{
expandedList[currGroup].Add(items[itemCount]);
}
}
}
return expandedList;
}
private static int[] GetItemsToInsertPerGroup(List<int> items, int totalGroups)
{
// Get average amount of items per list
int avgItemsPerGroup = (int)(items.Count / totalGroups);
int[] itemsToInsert = new int[totalGroups];
// Set each cell to be the average
for (int i = 0; i < itemsToInsert.Length; i++)
{
itemsToInsert[i] = avgItemsPerGroup;
}
// get how many items remain after inserting average amount
int remainingItems = items.Count - avgItemsPerGroup * totalGroups;
// Increase the amount needed per cell for each remaining item
for (int i = 0, j = 0;
i < remainingItems;
++i, ++j)
{
itemsToInsert[j]++;
}
return itemsToInsert;
}
Total items : 14
Total groups : 4
List 1 has 4 items
List 2 has 4 items
List 3 has 3 items
List 4 has 3 items
List 1 : 1 2 3 4
List 2 : 5 6 7 8
List 3 : 9 10 11
List 4 : 12 13 14