创建算法以根据项类型替换列表项

时间:2013-06-20 22:03:26

标签: c# algorithm list grouping

我必须创建一个交替项类型的列表。

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

组 - 类型
Group1 - 1
Group2 - 2
Group3 - 1
Group4 - 1
Group5 - 1
Group6 - 2
Group7 - 3

我想以这种方式重组项目:

组1 - 1
Group2 - 2
Group7 - 3
Group3 - 1
Group6 - 2
Group7 - 3
Group4 - 1
Group2 - 2
Group7 - 3
Group5 - 1
Group6 - 2
Group7 - 3

明白了吗?根据具有更多项目的类型的计数,我需要与其他项目交替。

此算法需要使用n种类型。

我有点失落,有人可以帮助我吗?这是一种什么样的算法怎么做?

3 个答案:

答案 0 :(得分:1)

我不知道这可以表现多少,但应该有效:

创建一个数组数组,在其中将第I组元素放在array [i] [j]中,所以你应该有类似的东西

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

array [1]:Group2,Group2

array [2]:Group3

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

最后,在您的数组行和“columns”之间循环,当您到达子数组的末尾时,使索引从0重新开始。它不漂亮,但应该可以正常工作。

对不起我的英语,我希望你能理解:)

答案 1 :(得分: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];
        }
    }
}

这是一个extension method,这意味着您可以这样调用它:

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 

答案 2 :(得分:0)

类似以下的作品,虽然我确信有更优雅的解决方案。

修改

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

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项。