如何在C#中从现有数组创建随机排序的新数组?
Hey there! 看你想要基于现有数组生成一个随机排序的新数组,同时保留原数组的顺序对吧?结合你给出的代码,我给你两种实用的实现方案:
你的需求与现有代码:
我希望从现有的数组创建一个随机排序的新数组,即将原数组的元素以随机顺序复制到新数组中。以下是我的现有代码:
MobileObjects[] array = new MobileObjects[3]; MobileObjects mob = new MobileObjects(); mob.name = ("Jawaharal"); mob.setPosition(); mob.id = 1; array[0] = mob; MobileObjects mob1 = new MobileObjects(); mob1.name = ("Willow"); mob1.setPosition(); mob1.id = 2; array[1] = mob1; MobileObjects mob2 = new MobileObjects(); mob2.name = ("Indira"); mob2.id = 3; mob2.setPosition(); array[2] = mob2; //shows whats in array foreach (MobileObjects host in array) { Console.WriteLine("Name : " + host.name + " "); Console.WriteLine("ID : " + host.id); Console.WriteLine("Position: " + host.position[0] + " " + host.position[1] + " " + host.position[2]); }
方案1:用LINQ快速实现(适合小型数组)
这个方法代码简洁,上手快,适合数组元素不多的场景:
// 保留你原有的数组初始化代码 MobileObjects[] array = new MobileObjects[3]; // ... 你的初始化代码省略 ... // 关键:生成随机排序的新数组 Random rng = new Random(); MobileObjects[] shuffledArray = array.OrderBy(item => rng.Next()).ToArray(); // 验证随机排序后的结果 foreach (MobileObjects host in shuffledArray) { Console.WriteLine("Name : " + host.name); Console.WriteLine("ID : " + host.id); Console.WriteLine("Position: " + host.position[0] + " " + host.position[1] + " " + host.position[2]); }
说明:
OrderBy(item => rng.Next())会给每个元素分配一个随机整数,然后根据这个整数排序,每次运行都会得到不同的顺序。ToArray()会生成一个全新的数组,原数组的元素顺序完全不受影响,完美符合你的需求。- 记得提前添加
using System.Linq;引用,不然LINQ方法会报错。
方案2:Fisher-Yates洗牌算法(高效首选)
如果你的数组元素较多,这个算法的效率更高(时间复杂度O(n)),而且是行业内公认的标准洗牌方案:
// 保留你原有的数组初始化代码 MobileObjects[] array = new MobileObjects[3]; // ... 你的初始化代码省略 ... // 第一步:复制原数组到新数组,避免修改原数组 MobileObjects[] shuffledArray = (MobileObjects[])array.Clone(); Random rng = new Random(); // 第二步:执行Fisher-Yates洗牌逻辑 int length = shuffledArray.Length; while (length > 1) { length--; // 生成随机索引 int randomIndex = rng.Next(length + 1); // 交换元素位置 MobileObjects temp = shuffledArray[randomIndex]; shuffledArray[randomIndex] = shuffledArray[length]; shuffledArray[length] = temp; } // 验证随机排序后的结果 foreach (MobileObjects host in shuffledArray) { Console.WriteLine("Name : " + host.name); Console.WriteLine("ID : " + host.id); Console.WriteLine("Position: " + host.position[0] + " " + host.position[1] + " " + host.position[2]); }
说明:
- 我们先用
array.Clone()复制原数组,这样原数组的顺序完全不变,洗牌操作只在新数组上进行。 - Fisher-Yates算法通过原地交换元素实现随机排序,没有额外的排序开销,比LINQ的
OrderBy更高效。
重要注意事项
- 不要在循环内创建
Random实例:如果在循环里每次都new Random(),会因为系统时钟的精度问题生成重复的随机数,导致排序没有变化。一定要提前创建一个Random对象复用。 - 浅拷贝 vs 深拷贝:如果
MobileObjects类里有引用类型的属性(比如position是自定义类的数组),Clone()只是浅拷贝,新数组和原数组会共享这些引用。如果需要完全独立的对象,你需要自己实现深拷贝方法(比如在MobileObjects里写一个Clone()方法,手动复制所有属性)。
内容的提问来源于stack exchange,提问作者Momo
相关产品推荐
相关产品推荐

