随机数组列表

本文关键字:列表 数组 随机 | 更新日期: 2023-09-27 17:50:45

我正试图与随机数组列表工作,这里是代码

private static string getSearchEngine()
{
    ArrayList url = new ArrayList();
    url.Add("www.google.com");
    url.Add("www.bing.com");
    url.Add("www.yahoo.com"); 
    Random rnd = new Random();
    int i = rnd.Next(0, url.Count);
    return url[i].ToString();
}
private static void DoMore_Functionality_Using_engName()
{
    for(int i = 0; i < 300; i++)
        string engName = getSearchEngine();
}

我希望每个搜索引擎只被使用100次。如果我使用上面的代码,随机化器可以选择其中的任何一个超过100次。我如何修改代码来做到这一点?

谢谢Rashmi

随机数组列表

我认为你可以通过在你的方法之外定义你的集合来做到这一点。将每个搜索引擎添加到您的列表100次,然后每次您随机选择一个引擎,从您的收集中删除该项目。像这样:

static List<string> engines = new List<string> (Enumerable.Repeat("www.google.com", 100)
        .Concat(Enumerable.Repeat("www.bing.com", 100))
        .Concat(Enumerable.Repeat("www.yahoo.com", 100)));
static Random rnd = new Random();
private static string getSearchEngine()
{
    int i = rnd.Next(0, engines.Count);
    var temp = engines[i];
    engines.RemoveAt(i);
    return temp;
}

这里有一种使用shuffle的方法:

List<string> urls = new List<string> { "www.google.com", "www.bing.com", "www.yahoo.com" };
List<int> randomIdx = new List<int> (Enumerable.Repeat(0, 100)
                                     .Concat(Enumerable.Repeat(1, 100))
                                     .Concat(Enumerable.Repeat(2, 100)));
Random r = new Random();
// This is the Fisher-Yates Shuffle
// see: http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
for (int i = randomIdx.Count - 1; i > 0; i--) 
{
    int j = r.Next(0,i);
    int tmp = randomIdx[i];
    randomIdx[i] = randomIdx[j];
    randomIdx[j] = tmp;
}
// Iterate through our random list and write each one out
for (int i = 0; i < randomIdx.Count; i++)
{
    Console.WriteLine(urls[randomIdx[i]]);
}

因此,要将此工作到您的DoMore_Functionality_Using_engName()函数中,您将在类中进行初始化,该初始化设置列表并对其进行洗牌,然后设置索引属性,以跟踪您在列表中的位置。然后在DoMore_Functionality_Using_engName()中,您将获得下一个结果,然后增加索引。

您需要将每个搜索引擎与使用次数的计数器相关联。为此,您需要将集合保存在内存中,而不是每次都创建它。

首先,创建一个类来表示数据:

class SearchEngine
{
    public SearchEngine(string url, int counter)
    {
        Url = url;
        Counter = counter;
    }
    public string Url { get; set; }
    public int Counter { get; set; }
}

第二,在某处创建一个引擎集合作为私有字段:

private Random _random = new Random();
private IEnumerable<SearchEngine> _engines = new[]
{
    new SearchEngine("www.google.com", 0),
    new SearchEngine("www.bing.com", 0),
    new SearchEngine("www.yahoo.com", 0)
};

获得随机搜索引擎的方法应该是这样的:

private string GetRandomSearchEngine()
{
    var searchEngine = _engines
    // randomize the collection
        .OrderBy(x => _random.Next())
    // skip items with invalid counter
        .SkipWhile(t => t.Counter >= 100)
        .First();
    // update the counter
    searchEngine.Counter++;
    return searchEngine.Url;
}

编辑

作为@Matt Burland建议使用_random.Next()是随机化集合的更好方法。他还提出了另一个有效的观点:当所有计数器都达到100时会发生什么?

在这种情况下,上面的代码将抛出一个异常(即First()方法)。假设您不需要,您可以使用FirstOrDefault()并检查null。如果返回的项目是null,则所有计数器已达到100。
private bool TryGetRandomSearchEngine(out string url)
{
    var searchEngine = _engines
    // randomize the collection
        .OrderBy(x => _random.Next())
    // skip items with invalid counter
        .SkipWhile(t => t.Counter >= 100)
        .FirstOrDefault();
    if(searchEngine != null)
    {        
        // update the counter
        searchEngine.Counter++;
        url = searchEngine.Url;
        return true;
    }
    url = String.Empty;
    return false;
} 

在代码的某个地方,你可以像这样使用上面的方法:

string searchEngineUrl;
while(TryGetRandomSearchEngine(out searchEngineUrl))
{
    PerformSearch(searchEngineUrl, searchTerms);
}