【问题标题】:Generate and repeat number in C#在 C# 中生成并重复数字
【发布时间】:2011-01-02 10:58:13
【问题描述】:

我想生成一个具有 144 个数字的数组,从 1->36 以随机顺序排列(因此每个数字重复 4 次)。我们可以使用 Enumerable.Repeat 和 Enumerable.Range 来做到这一点。如果是,请向我解释如何?

【问题讨论】:

    标签: c# repeat enumerable


    【解决方案1】:

    好吧,创建包含所有数字的序列很容易:

    var items = from x in Enumerable.Range(1, 36)
                from y in Enumerable.Repeat(x, 4)
                select y;
    

    然后您可以使用ToArray 将其放入一个数组并随机播放。有很多关于在 SO 上用 C# 洗牌数组的问题,例如this one。您可以直接使用该代码,也可以调用 ToArray 并在适当的位置打乱数组而不在最后产生它。

    【讨论】:

    • 比我的多个 Concat 更优雅;)
    • 感谢您的评论,但现在我需要将生成的数组填充到 [9,16] 数组中,您能给我推荐一个好方法吗?
    • @A New Chicken:我怀疑使用 Buffer.BlockCopy 对你有用……无论如何,它值得一试。 (即创建二维数组并使用 Buffer.BlockCopy 将一维数组复制到其中。)
    【解决方案2】:
    int[] numbers = Enumerable.Range(0, 144).Select(i => (i % 36)+1).OrderBy(g => Guid.NewGuid()).ToArray();
    

    【讨论】:

    • 在这种情况下可能并不重要,但这种洗牌方式最终是 O(n log n),而它只需要 O(n)。
    【解决方案3】:
    // Generate the list (not in random order)
    var one_to_36 = Enumerable.Range(1, 36);
    var lst = one_to_36.Concat(one_to_36).Concat(one_to_36).Concat(one_to_36).ToList();
    
    // Randomize the list by swapping random elements
    Random rnd = new Random();
    for(int i = 0; i < lst.Count; i++)
    {
        int i1 = rnd.Next(lst.Count);
        int i2 = rnd.Next(lst.Count);
        int tmp = lst[i1];
        lst[i1] = lst[i2];
        lst[i2] = tmp;
    }
    

    【讨论】:

    • 以这种方式交换随机元素并不能提供良好的随机分布 - 正如我的回答中所链接的那样,有一种更好的方式来洗牌。
    【解决方案4】:
    var seq = Enumerable.Range(0, 144);    
    var all = seq.ToList();
    var random = new Random();
    var result = seq.Select(i => {
     var index = random.Next()%all.Count;
     var r = all[index] % 36 + 1; all.RemoveAt(index);
     return r;
    }).ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-10
      • 2013-11-12
      • 2016-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      相关资源
      最近更新 更多