2010-02-28 144 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