2016-11-11 80 views
2

我正在製作一個基本的交易或不交易遊戲,因此我必須從數組中隨機挑選10個決賽選手,無需重複。消除數組c中的重複項#

我有我的結構和陣列設置了這樣的

public struct People 
{ 
    public string firstname; 
    public string lastname; 
    public int age; 
} 

class Program 
{ 
    public static People[] People1 = new People[40]; 
    public static People[] Finalists1 = new People[10]; 
    public static People[] Finalist1 = new People[1]; 

我的入圍方法中設置了這樣的

Random rand = new Random(); 

for (int i = 0; i < Finalists1.Length; i++) 
{ 
    num = rand.Next(0, People1.Length);   
    Finalists1[i].lastname = People1[num].lastname; 
    Finalists1[i].firstname = People1[num].firstname; 
    Finalists1[i].age = People1[num].age; 
} 

我怎樣才能消除重複的條目,同時維持10人陣中?

+1

那麼,你是什麼定義重複?相同的名字?姓?年齡?三個全部?無論如何,在StackOverflow上有十幾個問題,只需查看集合中的刪除重複項,或者選擇不同的值。 – HimBromBeere

+0

您可以創建一個已被選中的號碼列表,並確保新號碼不在所選號碼列表中。 – tphx

+1

以*隨機順序對數組進行排序*,拿起'10'然後 –

回答

5

由於初始數組不包含重複的,你可以在隨機順序排序並拿起10頂部項目:

Finalists1 = People1 
    .OrderByDescending(item => 1) // if people have some points, bonuses etc. 
    .ThenBy(item => Guid.NewGuid()) // shuffle among peers 
    .Take(10)      // Take top 10 
    .ToArray();      // materialize as an array 

如果人們選擇到最後不是完全隨機的(如選手可以賺取積分,獎金等)更改.OrderByDescending(item => 1),例如

 .OrderByDescending(item => item.Bonuses) 

如果你不想使用LINQ的,你可以借鑑urnPeople•不用返回:

 private static Random random = new Random(); 

    ... 

    List<People> urn = new List<People>(People1); 

    for (int i = 0; i < Finalists1.Length; ++i) { 
     int index = random.Next(0, urn.Count); 

     Finalists1[i] = urn[index]; 
     urn.RemoveAt(index); 
    } 
+0

當我寫這篇文章的時候,它只是前十,而不是任何洗牌順序。任何想法爲什麼? –

+1

@AlisterKyle:很好!語法錯誤:當Guid.NewGuid()需要*隨機*一個時,'new Guid'創建* zero *'Guid'。 –

+0

@DmitryBychenko,完美的工作。非常感謝 –

2

您可以保存已經繪製的數字的列表或哈希集合。然後再擲骰子以獲得另一個隨機數。

Random rand = new Random(); 

HashSet<int> drawnNumbers = new HashSet<int>(); 
for (int i = 0; i < Finalists1.Length; i++) 
{ 
    do 
    { 
     num = rand.Next(0, People1.Length); 
    } 
    while (drawnNumbers.Contains(num)); 

    Finalists1[i] = People1[num]; 
} 
+0

由於只有10名決賽選手參賽,我認爲用'List'取代'HashSet'會更好。對於最多10個項目,線性搜索速度更快,然後是哈希表特寫。 – Georg

+0

我知道,但我認爲這個想法是一樣的。只是想用OP的HashSet來思考線性搜索對大數據集的影響。 –

0

您可以更改的Finalists1類型的HashSet,不允許重複。 然後你的循環改變

while(Finalists1.Length < 10) 
{ 
    // random pick from array People1 (you don't need to create a new one) 
    num = rand.Next(0, People1.Length); 
    var toAdd = People1[num]; 
    // add to hash-set. Object won't be added, if already existing in the set 
    Finalists1.Add(toAdd); 
} 

你可能需要重寫People類的Equals方法,如果你真的需要創建一個新的對象添加到哈希集。

0

交換在People1每個選定的元素與數組的末尾,然後遞減數組結束索引,以便僅從下一次迭代中剩下的內容中進行選擇。

People tempPerson = new People; 
int lastElem = People1.length - 1; 
for (int i = 0; i < Finalists1.Length; i++) 
{ 
    num = rand.Next(0, lastElem + 1);   
    Finalists1[i] = People1[num]; 

    //swap last entry in People1 with People1[num] 
    tempPerson = People1[num]; 
    People1[num] = People1[lastElem]; 
    People1[lastElem] = tempPerson; 

    lastElem--; 
} 

對不起,如果有語法錯誤,我現在主要使用Java和C#。

順便說一句,您不必單獨設置字段,因爲每個數組都存儲Person類型的對象。

0

您可以將人員數組分組並選擇不同的方式。 如果您使用列表,您可以從列表中刪除人員 `var peopleArray = new People [40];

 var peopleCollection = peopleArray.GroupBy(p => new { p.age, p.firstname, p.lastname }).Select(grp => grp.FirstOrDefault()).ToList(); 

     var finalists = new People[10]; 


     var rand = new Random(); 

     for (var i = 0; i < finalists.Length; i++) 
     { 
      var index = rand.Next(0, peopleCollection.Count); 
      var person = peopleCollection[index]; 

      finalists[i].lastname = person.lastname; 
      finalists[i].firstname = person.firstname; 
      finalists[i].age = person.age; 

      peopleCollection.Remove(person); 
     } 
0

洗牌,並採取了第10位,例如

People1.Shuffle(); 
Finalists1= People1.Take(10).ToArray(); 

你可以找到StackOverflow的洗牌代碼或搜索「費雪耶茨洗牌C#」,下面的方法是從This SO Post拍攝。閱讀答案以獲取更多關於爲什麼不使用GUID的信息。

public static class ThreadSafeRandom 
    { 
     [ThreadStatic] private static Random Local; 

     public static Random ThisThreadsRandom 
     { 
      get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); } 
     } 
    } 

    static class MyExtensions 
    { 
    public static void Shuffle<T>(this IList<T> list) 
    { 
     int n = list.Count; 
     while (n > 1) 
     { 
     n--; 
     int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1); 
     T value = list[k]; 
     list[k] = list[n]; 
     list[n] = value; 
     } 
    } 
    }