C#创建随机唯一整数列表

时间:2011-11-02 14:12:59

标签: c# list unique distinct

我需要创建一个包含十亿个整数的列表,它们必须都是唯一的。我还需要非常快速地完成这项工作。

创建一个列表并逐个添加随机数并检查每个是否重复是非常慢的。

如果我只使用随机数填充列表而不检查它们是否重复,然后使用distinct()。toList(),这似乎相当快。我重复这个,直到没有重复。但是,创建新列表所使用的额外内存不是最佳的。有没有办法获得distinct()的性能,但它只是修改源列表而不是创建一个新列表?

6 个答案:

答案 0 :(得分:13)

整数是否需要在一定范围内?如果是这样,您可以创建一个数组或列表,其中包含该范围内的所有数字(例如1到1000000000)并随机播放该列表。

答案 1 :(得分:4)

我发现这是最快的,同时保持随机性:

        Random rand = new Random();
        var ints = Enumerable.Range(0, numOfInts)
                                     .Select(i => new Tuple<int, int>(rand.Next(numOfInts), i))
                                     .OrderBy(i => i.Item1)
                                     .Select(i => i.Item2);

...基本上为每个int分配一个随机id,然后按该id排序并选择生成的int列表。

答案 2 :(得分:2)

您可以在单独的HashSet<int>

中跟踪重复项
var set = new HashSet<int>();
var nums = new List<int>();

while(nums.Count < 1000000000) {
    int num;
    do {
        num = rand.NextInt();
    } while (!set.Contains(num));
    set.Add(num);
    list.Add(num);
}

您需要单独的List<int>来存储数字,因为哈希集不会保留您的随机排序。

答案 3 :(得分:2)

从字面上理解这个问题(一个包含10亿个整数的列表,它们必须都是唯一的):

Enumerable<int>.Range(0, 1000000000)

但是按照CodeCaster的回答,您可以创建列表并同时对其进行随机播放:

var count = 1000000000;
var list = new List<int>(count);
var random = new Random();
list.Add(0);
for (var i = 1; i < count; i++)
{
    var swap = random.Next(i - 1);
    list.Add(list[swap]);
    list[swap] = i;
}

答案 4 :(得分:1)

如果您绘制的可能整数的数量(比如因子2)明显大于您想要的整数数量,则只需使用HashSet<T>来检查重复项。

List<int> GetUniqueRandoms(Random random, int count)
{
  List<int> result = new List<int>(count);
  HashSet<int> set = new HashSet<int>(count);
  for(int i = 0; i < count; i++)
  {
    int num;

    do
    {
      num = random.NextInt();
    while(!set.Add(num));

    result.Add(num);
  }
  return result;
}

这会为集合分配正确的容量,以避免在增长期间重新分配。由于您的藏品很大,这应该是一个很大的改进。

您也可以一次使用Distinct

IEnumerable<int> RandomSequence(Random random)
{
    while(true)
    {
      yield return random.NextInt();
    }
}

RandomSequence(rand).Distinct().Take(1000000000).ToList();

但是对于这两种解决方案,您需要足够的内存来HashSet<int>List<int>


如果您绘制的可能整数的数量与您想要的整数数量一样大,您可以创建一个包含所有整数的数组,将它们随机播放,最后切断那些您不感兴趣的数组。

您可以使用Jon Skeet's shuffle implementation

答案 5 :(得分:0)

如果您以排序但仍然随机的方式创建列表(例如将随机数添加到列表的最后一个元素作为下一个元素),然后使用Fisher-Yates-Durstenfeld对列表进行洗牌,该怎么办?这将在整体线性时间内执行,这与列表生成一样好。但是,它可能会产生一些影响分布的显着偏差。