4

我想为变量分配vStreamID一个随机数。只要我的字典md_StreamDict包含生成的数字,这个数字就应该是新生成的。

长版:

vStreamID = (new Random()).Next(1000, 9999).ToString();
while (md_StreamDict.ContainsKey(vStreamID)) {
    vStreamID = (new Random()).Next(1000, 9999).ToString();
}

我想看看 LINQ 风格的东西

md_StreamDict.ContainsKey(vStreamID)
    .while( x => x = (new Random())
    .Next(1000, 9999)
    .ToString();

我知道上面的例子是香蕉。但是,如果有真正的方法可以实现这一目标,我会很高兴。不,我们不会再次开始通常的关于可读性的讨论。;)

4

5 回答 5

4

您需要一种为流式随机数生成无限可枚举的方法。您可以使用Enumerable.Range(0, int.MaxValue) 进行近似计算:

var rand = new Random();
var r = Enumerable.Range(0, int.MaxValue)
    .Select(s => rand.Next(1000, 9999))
    .SkipWhile(s => md_StreamDict.ContainsKey(s.ToString()))
    .First();

然后r将包含字典中未包含的新键值。

于 2012-12-28T13:48:00.373 回答
4

如果我理解正确,您只需要一个众所周知范围内的数字,并且该数字不应该已经在字典中,所以不要这样做Random

Enumerable.Range(1000, 9999)
          .Where(n => !dict.ContainsKey(n))
          .FirstOrDefault();
于 2012-12-28T13:48:54.410 回答
3

这里还有一些香蕉:

您可以创建一个 IEnumerable 来生成随机数,例如:

public class RandomList : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        Random r = new Random();

        while (true)
            yield return r.Next(1000, 9999);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

然后你可以这样做:

// I guess one could implement a seed constructor, if one was so inclined
RandomList rl = new RandomList(); 

int vStreamID = rl.SkipWhile(i => md_StreamDict.ContainsKey(i)).First();
于 2012-12-28T13:50:01.150 回答
2

现在我已经将您的问题读了 3 遍,但我仍然不知道为什么(或如何)有人会使用 LINQ 表达式来做到这一点。我看到的唯一较短的解决方案是我在评论中写的:

var r = new Random();

do {
    vStreamID = r.Next(1000, 9999).ToString();
} while (md_StreamDict.ContainsKey(vStreamID));
于 2012-12-28T13:45:30.993 回答
2

一种方法是使用 yield 返回值

 private static Random rand = new Random();

    private static void Test()
    {
        Dictionary<string, string> values = new Dictionary<string, string>();
        string vStreamId = GetNewValues().Where(x => !values.ContainsKey(x)).First();
    }

    public static IEnumerable<string> GetNewValues()
    {
        While(true)
        {
           yield return rand.Next(1000, 9999).ToString();
        }
    }

请注意,如果您在每个循环上生成一个新的 Random,则每次都将获得相同的值,因为它基于系统时钟。

于 2012-12-28T13:50:06.450 回答