根据分组顺序对列表中的项目进行洗牌

本文关键字:项目 列表 顺序 | 更新日期: 2023-09-27 17:53:07

我有一个对象列表。它们每个都有距离属性。我想打乱每一组中项目的顺序。为例:如果10个元素的距离为0,20个元素的距离为5,我就必须洗牌距离为0的元素,然后洗牌距离为5的元素。它不应该打乱distance=0和distance=5之间的关系。

我一直在尝试随机和分组的一些事情,但没有给我适当的结果。

谁能给我点光?

根据分组顺序对列表中的项目进行洗牌

一旦您有了洗牌序列的方法:

public static IEnumerable<T> Shuffle<T>(
    this IEnumerable<T> source, Random random)
{
    var list = source.ToList();
    for (int i = list.Count; i > 0; i--)
    {
        var index = random.Next(i);
        var temp = list[index];
        list[index] = list[i - 1];
        list[i - 1] = temp;
        yield return temp;
    }
}

你只需要将项目分组,并将每一组投影到该组的洗牌版本:

var random = new Random();
var query = data.GroupBy(item => item.Distance)
    .SelectMany(group => group.Shuffle(random));

示例Item class:

public class Item
{
    private static int index = 0;   // for test purposes
    public int Distance { get; set; }
    public object Data { get; set; }
    public Item(int distance)
    {
        this.Distance = distance;
        this.Data = ++index;
    }
}
代码:

List<Item> list= new List<Item>
{
    new Item(10),
    new Item(10),
    new Item(10),
    new Item(10),
    new Item(10),
    new Item(20),
    new Item(20),
    new Item(20),
};
Random rnd = new Random();
foreach (var group in from e in list
                      orderby rnd.NextDouble()
                      group e by e.Distance into g
                      orderby g.Key
                      select g)
{
    Console.WriteLine("Group with distance {0}", group.Key);
    foreach (var item in group)
    {
        Console.WriteLine("Item Distance={0}, Data={1}", item.Distance, item.Data);
    }
    Console.WriteLine("----");
}
结果:

Group with distance 10
Item Distance=10, Data=3
Item Distance=10, Data=1
Item Distance=10, Data=2
Item Distance=10, Data=5
Item Distance=10, Data=4
----
Group with distance 20
Item Distance=20, Data=7
Item Distance=20, Data=6
Item Distance=20, Data=8
----

假设这是你的类

public class Element
{
    public int Distance { get; set; }
    public string Name { get; set; }
}

里面有这些元素

List<Element> myList = new List<Element>();
myList.Add(new Element() { Distance = 10, Name = "test1" });
myList.Add(new Element() { Distance = 10, Name = "test2" });
myList.Add(new Element() { Distance = 20, Name = "test3" });
myList.Add(new Element() { Distance = 20, Name = "test4" });

则按距离对元素进行分组并打乱包含

元素的列表
Random rnd = new Random();
var Result = myList.GroupBy(r => r.Distance)
    .Select(x => new[] {
        new {
        Group =  x.Key, 
        Items =  x.Select(r => r.Name).OrderBy(_ => rnd.Next())
        }
    });

可以简化@Servy示例:

var query = data.GroupBy(item => item.Distance)
    .SelectMany(group => group.OrderBy(Guid.NewGuid()));