2016-11-11 75 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; 
     } 
    } 
    }