我有一个扩展名,可以将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;
}
以下是该方案:
我有一个列表,它有13个项目(项目可能会有所不同)。
在这个特定的例子中,由于我将列表分成4组,我正在
第2组:4项
第3组:4项
每组4项来自
int itemsPerGroup = (int)Math.Ceiling((double)items.Count / totalGroups);
现在这是错的,理想情况下我应该
同样的,当我尝试将其分成6组时,我得到了
你也可以在附图中看到这个
理想情况下应该
我在这里缺少什么?我该如何解决这个问题?
答案 0 :(得分:1)
因为你想要每组中的平均值,并且只要需要它,所以我可以建议这个算法。
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;
}
优点是,它很简单,考虑到O(n ^ 2),就像任何二维算法一样。设计思路是:找到平均值,找到平均值后的N =缺失元素,让前N个元素得到一个额外的元素来填补空白。
答案 1 :(得分:0)
我会每次计算每组的项目。
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);
}
答案 2 :(得分:0)
我会计算每组的项目(地板而不是天花板):
int itemsPerGroup = (int)Math.Floor((double)items.Count / totalGroups);
然后我会弄清楚剩余物品的数量:
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;
}
答案 3 :(得分:0)
如何以另一种方式进行, 比如说你有13件你想要6组 所以拿(如int)(13/6)并将其放置,这将给你2.现在有相同数量的组(6)乘以组大小(2)给你12.你有13个项目所以你有剩下一个,将其添加到第一组。应该给你一组nizer。
答案 4 :(得分:0)
如果您将for循环调整为此类
<div class="nav">
<ul>
<li><a href="#">Home</a>
</li>
<li><a href="#">About</a>
</li>
<li><a href="#">Contact</a>
</li>
<li><a href="#">Portfolio</a>
</li>
<li><a href="#">FAQ</a>
</li>
</ul>
</div>
答案 5 :(得分:0)
如果组中各项目的顺序不相关,那么您可以通过按模块分组数来对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));
}
会有这些结果
第1组:1,7,13
第2组:2,8
第3组:3,9
第4组:4,10
第5组:5,11
第6组:6,12
答案 6 :(得分:0)
我想你应该做的是计算每个桶的平均物品数量(也就是List),然后将其插入每个桶中,然后插入其余的物体。
注意:保持订单,<int>
可以替换为<T>
例如:
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