简体   繁体   English

用C#从id集合中获取4个(或任意数量)随机唯一ID的最简单方法是什么?

[英]What is the easiest way to get 4(or any count) random unique ids from an id collection with c#?

Assume that you have an idCollection IList<long> and you have a method to get 4 unique ids.Every time you call it, it gives you random 4 unique ids ? 假设您有一个idCollection IList<long>并且有一个获取4个唯一ID的方法,每次调用它都会给您随机提供4个唯一ID?

var idCollec = new[] {1,2,3,4,5,6,7,8,9,10,11,12}.ToList();

For example {2,6,11,12}
            {3,4,7,8}
            {5,8,10,12}
            ...
            ..

What is the smartest way to do it ? 最聪明的方法是什么?

Thanks 谢谢

Seems like easiest way would be to have something like: 似乎最简单的方法是:

if(idCollection.Count <4)
{
    throw new ArgumentException("Source array not long enough");
}
List<long> FourUniqueIds = new List<long>(4);
while(FourUniqueIds.Count <4)
{
    long temp = idCollection[random.Next(idCollection.Count)];
    if(!FourUniqueIds.Contains(temp))
    {
        FourUniqueIds.add(temp);
    }
}

It can be done with a nice LINQ query. 可以使用一个不错的LINQ查询来完成。 The key to doing it without the risk of getting duplicates, is to create a never ending IEnumerable of random integers. 做到无重复风险的关键是创建一个永无休止的IEnumerable随机整数。 Then you can take n distinct values from it, and use them as indexes into the list. 然后,您可以从中获取n个不同的值,并将它们用作列表的索引。

Sample program: 示例程序:

using System;
using System.Collections.Generic;
using System.Linq;

namespace TestRandom
{
    class Program
{
    static void Main(string[] args)
    {
        // Just to prepopulate a list.
        var ids = (from n in Enumerable.Range(0, 100)
                   select (long)rand.Next(0, 1000)).ToList();

        // Example usage of the GetRandomSet method.
        foreach(long id in GetRandomSet(ids, 4))
            Console.WriteLine(id);
    }

    // Get count random entries from the list.
    public static IEnumerable<long> GetRandomSet(IList<long> ids, int count)
    {
        // Can't get more than there is in the list.
        if ( count > ids.Count)
            count = ids.Count;

        return RandomIntegers(0, ids.Count)
            .Distinct()
            .Take(count)
            .Select(index => ids[index]);
    }

    private static IEnumerable<int> RandomIntegers(int min, int max)
    {
        while (true)
            yield return rand.Next(min, max);
    }

    private static readonly Random rand = new Random();
}

} }

If you use this approach, make sure you do not try to take more distinct values than there are available in the range passed to RandomIntegers. 如果使用这种方法,请确保不要尝试使用比传递给RandomIntegers的范围内可用的值更多的不同值。

What about shuffling the set then just taking the first four each time? 洗牌然后每次只拿前四个呢?

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> e)
{
    var r = new Random();
    return e.OrderBy(x => r.Next());
}

Then something like this? 那是这样的吗? It would probably be faster to use a for loop instead of Take and Except. 使用for循环代替Take和Except可能会更快。

 var ordered = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 10};

 var random = ordered.Shuffle();
 while(random.Count() > 0)
 {
     var ourSet = random.Take(4).ToList();            
     random = random.Except(ourSet);
 }

If the IList <long> is populated with non unique values, you could use LINQ's Distinct() in combination with Take(), if it already has unique values, just use Take(). 如果IList <long>填充有非唯一值,则可以将LINQ的Distinct()与Take()结合使用,如果它已经具有唯一值,则只需使用Take()。

List<long> myUniqueIds = //prepoulation
var first4UniqueUnused = myUniqueIds.Take(4);

var next4UniqueUnused = myUniqueIds.Where(l=>!first4UniqueUnused.Contains(l)).Take(4);

another way that is too easy, i think we've been making it too hard: 另一种太简单的方式,我认为我们一直在努力:

List<long> myIDs = //prepopulation;
List<long> my4Random = new List<long>();
Random r = new Random();

for(int i=0; i< 4; i++)
{
     int j = r.Next();
     while(j>myIDs.Count || my4Random.Contains(myIDs[j]))
          j = r.Next();

     my4Random.Add(myIDs[j]);
}
Random random = new Random(); 

long firstOne = idCollection[random.Next(idCollection.Count)];
long secondOne = idCollection[random.NExt(idCollection.Count)];

...and so on ...等等

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在C#中生成准随机数的最简单方法是什么? - What is the easiest way to generate quasi random numbers in C#? 在C#中获取OutOfMemoryException的最简单方法是什么? - What's the easiest way to get an OutOfMemoryException in C#? 使用C#从RTMP服务器获取和播放音频流的最简单方法是什么? - What is the easiest way to get and play audio stream from RTMP server using C#? 在C#中从bool转换为字符串的最简单方法是什么? - What's the easiest way to convert from a bool to string in C#? 从Javascript调用C#方法的最简单方法是什么? - What is the easiest way to call a C# method from Javascript 判断一组 id 中哪些 id 仍在数据库中的有效方法(即将输入 id 与集合 id 相交)MongoDb C# - Effective way to tell what ids in a set of ids are still in the database (I.e intersect input ids with collection ids) MongoDb C# 从C#中的Brushes集合中选择随机画笔的最佳方法是什么? - What is the best way to pick a random brush from the Brushes collection in C#? 在 C# 中减去时间的最简单方法是什么? - What is the easiest way to subtract time in C#? 使用c#,NPOI和XSSF工作簿计算.xlsx工作簿表的最简单方法是什么? - What is the easiest way to count .xlsx workbook sheets using c#, NPOI and an XSSF workbook? 在C#中,递归获取父ID列表的最佳方法是什么? - In C#, what is the best way to get a list of parent Ids recursively?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM