2010-02-28 118 views
7

我忙于编写数组的C#中。我可以用随机生成填满它,但现在是我的问题我如何做到这一点,但这样我可以检查是否值已经是数组中,如果是产生新的价值C#中的随机数生成器 - 唯一值

额外的信息:
最大值:100
元素的数量:100

重要PLZ工作的进一步ON MY IDEA

我的想法

public void FillArray(int[] A, int Range) 
{ 
    for (int I = 0; I < A.Length; I++) 
    { 
     A[I] = ValidNumber(T, I, Range); 
    } 
} /* Fill Array */ 

选择执行排序

public void SelectionSort(int[] A) 
{ 
    int K, X; 
    for (int I = 0; I < A.Length - 1; I++) 
    { 
     K = I; 
     X = A[K]; 
     for (int J = I + 1; J < A.Length; J++) 
     { 
      if (A[J] < X) 
      { 
       K = J; 
       X = A[K]; 
      } 
     } 
     A[K] = A[I]; 
     A[I] = X; 
    } 
} /* Selection sort */ 

这些都只是一些想法,现在我想知道我可以修复它,这样我可以看看有选择排序,如果有ALLREAD那里(fillarray)是相同的,如果这样更换具有新的随机值。所以我想用随机顺序创建一个随机数组(从1到100)

+1

闻起来像作业,特别是与下面的评论(有效,良好)的建议与框架,似乎是作业的一部分:“从这个代码开始” – 2010-02-28 15:16:41

+0

是的这确实是作业的一部分,我不会说谎,我只是卡在一个部分,并希望如此提示/反馈,这是不坏,我想 – ShallowHeart 2010-02-28 15:30:47

+1

正确的代码缩进和更好的变量名称将帮助人们了解你的代码,并因此给你更好的解决方案。 – CesarGon 2010-02-28 15:35:14

回答

6

以下将以随机顺序生成数字为1-100的数组。

Random rnd = new Random(); 
    var randomNumbers = Enumerable.Range(1, 100).OrderBy(i => rnd.Next()).ToArray(); 
+0

你应该给'Random()'提供一个种子,例如'Random(DateTime.Now.Millisecond)' – AxelEckenberger 2010-02-28 14:37:48

+8

Random上的空构造函数默认为这样(Enviroment.TickCount) – 2010-02-28 14:39:07

+10

@Obalix:不,你不应该这样做。如果您希望稍后能够再次提供**相同的种子,则只应提供种子。否则,依靠默认播种。 – 2010-02-28 14:40:11

2

这里有一个天真的实现:

int[] values = new int[100]; 
Random random = new Random(); 
for(int i = 0; i < values.Length; i++) 
{ 
    int v; 
    do 
    { 
     v = random.Next(100) + 1; 
    } while (Array.IndexOf(values, v) != -1) 
    values[i] = v; 
} 

但是这将是非常低效的,尤其是靠近数组的结尾......

一个更好的解决办法是要考虑的是,由于你需要100个不同的值,从1到100以随机顺序排列,你的数组最终将包含从1到100的所有可能的值。所以你只需要生成这些值的序列,并“洗牌”它:

int[] values = Enumerable.Range(1, 100).ToArray(); 
Random random = new Random(); 
for(int i = values.Length - 1; i > 0; i--) 
{ 
    int j = random.Next(i + 1); 
    int tmp = values[i]; 
    values[i] = values[j]; 
    values[j] = tmp; 
} 

编辑:更好的方法,应该少特定情况下工作:

T[] RandomCombinationWithNoRepeat<T>(IEnumerable<T> itemsToPickFrom, int numberOfItemsToPick) 
{ 
    // Copy original items to pick from, because we need to modify it 
    List<T> itemsCopy = new List<T>(itemsToPickFrom); 
    T[] array = new T[numberOfItemsToPick]; 
    Random random = new Random(); 
    for(int i = 0; i < numberOfItemsToPick; i++) 
    { 
     // Pick item and remove it from list 
     int index = random.Next(itemsCopy.Count); 
     array[i] = itemsCopy[index]; 
     itemsCopy.RemoveAt(index); 
    } 
    return array; 
} 

在你的情况,你会使用它这样的:

int[] result = RandomCombinationWithNoRepeat(Enumerable.Range(1, 100), 100); 
+0

我更寻找一个接力 溶液 \t 是被更思考一个OOP编程是这样的[代码]公共无效FillArray(INT [] A,INT范围){对于(INT I = 0; I < A.Length; I ++ A [I] = ValidNumber(T,I,Range)} [/ code]在这个小想法后,我卡住了 毕竟我也编码非常严格我保持输入,处理和输出在不同的类 – ShallowHeart 2010-02-28 14:52:16

+0

我不认为'列表'包含一个属性'长度',你可能想'Count'。 – 2012-09-25 15:34:53

+0

@PhilippeLavoie,是的,你是对的...我修好了,谢谢! – 2012-09-25 17:32:33

5

从你的描述我认为你需要一个100个整数的数组,数值从1到100并且没有重复的数字。如果数字是整数,则不需要生成随机数字,因为所有可能的数字都在数组中。因此,只有订单或数字可以随机化。

使用Linq和Jesper Palm的方法 - 通过Thomas Levesque的以下语句将为您提供所需的数组。

Random rnd = new Random(); 
var randomNumbers = Enumerable.Range(1, 100) 
           .Select(x => new { val = x, order = rnd.Next() }) 
           .OrderBy(i => i.order) 
           .Select(x => x.val) 
           .ToArray(); 

该方法甚至相当快,明显比任何比较操作更高效。

为了解释上述的原来的海报,请参阅评论如下:

  • Enumerable.Range(1, 100)创建一个范围从1开始,并在100结束整数。
  • .Select(x => new { val = x, order = rnd.Next() })创建一个新的临时对象,其中包含由随机数确定的值和顺序位置。
  • .OrderBy(i => i.order)按临时对象的顺序排序临时对象。
  • .Select(x => x.val)选择临时对象的值,从而转换回int。
  • .ToArray()将整个事情再次变回数组。

使用的语法是在.NET 3.5中可用的LINQ。对于旧版本,你必须自己实现它,这要复杂得多,而且时间更长。

继Eric的评论:如果shuffeling被requried你可以做如下代码

var list = myInputList; 
var result = list.Select(x => new { val = x, order = rnd.Next() }) 
       .OrderBy(i => i.order) 
       .Select(x => x.val) 
       .ToArray(); 
+0

thnx你所有的答案,但可以请看看我的想法 Btw ho你是否在那个灰色框中添加了代码?是的,我在这附近是一个新手。 另外我想说明的是,我是c#的新手只有几个月的经验。 我甚至不知道你们在这里的一些东西,甚至我喜欢enumerable.range,必须是范围。必须订购它。但我想它的代码将排列在数组中的所有数字什么是不是我想要达到的概念。 我想随机选择一个随机数组,其中100个元素的数字在1到100之间。 – ShallowHeart 2010-02-28 15:00:42

+0

@ShallowHeart,我想你错过了这一点。代码采用1到100的数字,然后将它们“排序”为*随机确定的顺序*。这是洗牌的标准技术。 – 2010-02-28 16:28:49

+0

@Obalix你的回答节省了我很多时间。 你能告诉我,如果我想得到一个数组30个最大范围变化的数字,我需要做什么? 我所做的是使用你的代码片段生成完整范围的随机数组,并将所需的前30个元素存储在我的数组中。我怎样才能修改这段代码来加入甚至减少循环时间。 – Jerin 2014-07-14 12:36:05

0
从我所了解

。你需要一个随机数的整数集合。我假设使用int数组或List的int无关紧要。 这是一个简单的完整方法,你已经描述过了。
using System; using System.Collections.Generic; using System.Text;

namespace FillRandom { class Program { static void Main(string[] args) { int minValue = 1; int maxValue = 100; //create a list of int with capacity set as 100 List array = new List(100);

 FillArray(array, minValue, maxValue, array.Capacity); 

     //print out all values in the array 
     foreach (int i in array) 
     { 
      Console.WriteLine(i); 
     } 
    } 

    private static void FillArray(List<int> array, int minValue, int maxValue, int capacity) 
    { 
     int count = 0; 
     while (array.Count != capacity - 1) 
     { 
      Random rnd = new Random(); 
      int value = rnd.Next(minValue, maxValue); 
      if (!array.Contains(value)) 
      { 
       array.Add(value); 
      } 
      count++; 
     } 
     //print out the number of times the looping occurs 
     Console.WriteLine("count: "+count); 
    }   
} 

}

您可以创建一个控制台项目并试一试。

+0

埃里克是完全正确的,这是一个坏主意,我试图用“count”打印出来。 ;)无论如何,一个有趣的发现是,如果每次创建一个新的Random对象(大约100k到200k循环),但使用相同的对象时,它实际上使填充数组更难,但使用相同的对象需要大约500次。 – Blithe 2010-03-02 14:46:10

30

我如何做到这一点,但这样我可以检查是否值已经是数组中,如果是产生新的价值

你不这样做,直到永远,因为那是一个非常糟糕的主意

为了说明为什么它是一个可怕的想法,可以考虑同样的问题的另一个版本:通过下列方法一百万的数字为随机进行排序:

  1. 选择从一个数百万。
  2. 检查它是否已经在列表中。
  3. 如果是,请返回步骤1
  4. 否则,将该号码添加到列表中。
  5. 该清单上是否有一百万件物品?如果是,你就完成了。如果不是,请返回步骤1.

很明显,这是有效的。这是个好主意吗?假设你快完成了。该清单上有999999项。唯一缺少的项目是857313.你是做什么的?你选择一个随机数字,比如12。现在你检查列表上的999999项目,看它们中的任何一个是否为12. 12可能是你选择的第一个数字之一,所以它可能会很快找到它。或者它可能是最后一个,所以需要很长时间。平均来说,需要500000个支票来查看列表中是否有12个。而且,因为列表中只有一个数字。

12没有解决。回到起点。选择另一个随机数字,比如说53259.是否在列表中?另有五十万支票。

继续这样做,直到您生成857313,每100万次尝试一次。

因此,平均而言,将最后一个项目放在列表中需要500000 x 1000000 =五千亿比较。它可能会更多。它可能需要几万亿次比较。或者你可能会很幸运,而且需要一个。但平均来说,有50万亿次比较。

这是一个可怕的方式来产生一个列表的随机排序。

有两种好方法可以对列表进行随机排序。

(1)制作一个设备,它可以对给定排序功能的列表进行排序。提供基于随机种子的稳定排序。

请注意,您应该而不是产生一个随机排序通过使一个方法返回随机结果时问“是比A大吗?这是一个不稳定的顺序;许多排序算法都是基于稳定的排序顺序进行预测的,当排序顺序不稳定时会进入无限循环或出现其他不良行为。

这个算法是O(n lg n),并且具有很好的属性,它很容易写出标准部件,就像其他答案指出的那样。对于典型实现中的小列表来说,它的速度也非常快。

(2)随机从源列表中选择一个索引项,从源列表中删除,并将其放在目标列表中。

后者被称为Knuth Shuffle或Fischer-Yates Shuffle,它是一个非常快速的算法。您可以“就地”完成此操作,将现有数组变为洗牌顺序或创建新列表。它还有一个很好的属性,你可以“付费玩”,根据需要对列表中的“顶部”进行洗牌。如果你有一百万件物品需要洗牌,但你只需要第一百件,那么你就可以制定出第一百件物品的分类顺序,并称之为好。

+1

我觉得第二个建议很出色。 – 2012-09-06 06:40:45

+0

伟大的答案,这是一个很好的方法,因为这个问题涉及到功课,你不只是说这个复制,你已经完成+1 – 2012-09-26 00:49:26

+0

我现在使用第二种方法,它是美好的。很好的答案,+1。 – Abluescarab 2013-12-21 14:26:08