1

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

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

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

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

组1 - 1
组 2 - 2 组 7
- 3组 3
- 1 组 6 -
2组 7 - 3 组 4 - 1 组 2 - 2 组 7 - 3组 5 - 1 组 6 - 2组 7 - 3






理解?基于具有更多项目的类型的计数,我需要与其他项目交替。

该算法需要包含 n 个类型。

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

4

3 回答 3

1

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

创建一个数组数组,将组 I 的元素放入数组 [i] [j] 中,因此您应该有类似

数组 [0]:组 1、组 3、组 4、组 5

数组[1]:组 2,组 2

数组[2]:组 3

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

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

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

于 2013-06-20T22:32:17.550 回答
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 
于 2013-06-20T22:41:59.093 回答
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项目。

于 2013-06-20T22:59:44.470 回答