Reputation: 121
I am trying to work with Random array list and here is the code
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();
}
I want each search engine to be used only 100 times. If I use the above code, the randomizer could pick any one of them more than 100 times. How can I modify the code to do this?
Thanks Rashmi
Upvotes: 0
Views: 1643
Reputation: 9566
You need to associate each search engine with a counter of how many times it was used. To do so, you'll need to keep the collection in memory and not create it each time.
First, create a class to represent your data:
class SearchEngine
{
public SearchEngine(string url, int counter)
{
Url = url;
Counter = counter;
}
public string Url { get; set; }
public int Counter { get; set; }
}
Second, create a collection of your engines as a private field somewhere:
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)
};
And the method to get a random search engine should be like this:
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;
}
EDIT
As @Matt Burland suggests using _random.Next()
is a better approach to randomizing the collection.
He also raises another valid point: what happens when all the counters reach 100?
In such case, the code above will throw an exception (namely, the First()
method). Assuming you don't want that you can use FirstOrDefault()
and check for null
. If the returned item is null
then all counters have reached 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;
}
And somewhere in your code you can use the method above like this:
string searchEngineUrl;
while(TryGetRandomSearchEngine(out searchEngineUrl))
{
PerformSearch(searchEngineUrl, searchTerms);
}
Upvotes: 0
Reputation: 45135
Here's a way to do it with a 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]]);
}
So to work this into your DoMore_Functionality_Using_engName()
function, you would have an initialization in your class that sets up the list and shuffles it and then sets an index property that will keep track of where you are in the list. Then in DoMore_Functionality_Using_engName()
, you would get the next result and then increment the index.
Upvotes: 1
Reputation: 101681
I think you can do this by defining your collection outside of your method.Add each search engine for 100 times to your list, then each time you pick a random engine, remove that item from your collection.Something like this:
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;
}
Upvotes: 3