创建一个算法来根据项目类型替换列表项目

本文关键字:项目 类型 列表 替换 算法 一个 创建 | 更新日期: 2023-09-27 18:19:22

我必须创建一个列表,交替条目类型。

在我原来的列表中,我有这个:

组-类型
Group1 - 1
Group2 - 2
第3 - 1组
第4 - 1组
组5 - 1
第6 - 2组
第7 - 3组

我想用这种方式重新组织项目:

Group1 - 1
Group2 - 2
第7 - 3组
第3 - 1组
第6 - 2组
第7 - 3组
第4 - 1组
Group2 - 2
第7 - 3组
组5 - 1
第6 - 2组
第7 - 3组

明白吗?根据项目较多的类型的计数,我需要与其他项目交替使用。

该算法需要包含n个类型

我有点迷路了,有人能帮帮我吗?这是一种怎样的算法?

创建一个算法来根据项目类型替换列表项目

我不知道这能执行多少,但应该是功能:

创建一个数组的数组,在数组中放入数组[I][j]中第I组的元素,所以你应该有像

这样的内容

array[0]: Group1, Group3, Group4, Group5

array[1]: Group2, Group2

阵列[2]:Group3

,然后为每个数组保存一个指向刚刚添加的元素的索引

最后,在数组的行和"列"之间循环,当到达子数组的末尾时,使索引从0重新开始。它不漂亮,但应该没问题。

很抱歉我的英语不好,希望你能理解:)

这是我的第一次尝试,尽管我确信这可以改进:

public static IEnumerable<TSource> AlternateGroups<TSource, TKey>(this IEnumerable<TSource> list, Func<TSource, TKey> keySelector)
{
    var groups = list.GroupBy(keySelector).OrderByDescending(g => g.Count());
    var largestGroup = groups.First();
    var arrays = groups.Skip(1).Select(g => g.ToArray());
    var index = new int[arrays.Count()];
    foreach(var item in largestGroup)
    {
        yield return item;
        var i = 0;
        foreach(var a in arrays)
        {
            yield return a[index[i++]++ % a.Length];
        }
    }
}

这是作为扩展方法编写的,这意味着您可以这样调用它:

var input = new[] 
{
    new { Group = "Group1", Type = 1 },
    new { Group = "Group2", Type = 2 },
    new { Group = "Group3", Type = 1 },
    new { Group = "Group4", Type = 1 },
    new { Group = "Group5", Type = 1 },
    new { Group = "Group6", Type = 2 },
    new { Group = "Group7", Type = 3 },
};
var results = input.AlternateGroups(x => x.Type);
// Group1 1 
// Group2 2 
// Group7 3 
// Group3 1 
// Group6 2 
// Group7 3 
// Group4 1 
// Group2 2 
// Group7 3 
// Group5 1 
// Group6 2 
// Group7 3 

虽然我相信有更优雅的解决方案,但类似于下面的工作。

编辑:

正如在评论中指出的那样,我没有意识到应该重用较短列表中的元素来组成最长分组列表的长度。这是修改后的版本。

void Main()
{
    var list = new List<Group>{
        new Group { Name = "Group1", Type = 1 },
        new Group { Name = "Group2", Type = 2 },
        new Group { Name = "Group3", Type = 1 },
        new Group { Name = "Group4", Type = 1 },
        new Group { Name = "Group5", Type = 1 },
        new Group { Name = "Group6", Type = 2 },
        new Group { Name = "Group7", Type = 3 }
    };
    var groups = list.GroupBy(g => g.Type).ToList();    
    var groupCounts = groups.Select(g => g.Count()).ToArray();  
    var biggestGroup = groupCounts.Max();
    var newList = new List<Group>();
    for (int i = 0; i < biggestGroup; i++)
    {
        for (int j = 0; j < groups.Count; j++)
        {
            var element = groups[j].ElementAt(i % groupCounts[j]);
            newList.Add(element);
        }
    }   
    // newList contains the ordered items
}
public class Group 
{
    public string Name { get;set; }
    public int Type { get;set; }
}

输出
Group1 1 
Group2 2 
Group7 3 
Group3 1 
Group6 2 
Group7 3 
Group4 1 
Group2 2 
Group7 3 
Group5 1 
Group6 2 
Group7 3

你可以把它做成一个扩展方法来返回IEnumerable<Group>yield return的项目