In a list like this:
var colors = new List<string>{"green", "red", "blue", "black","purple"};
I can get the first value like this:
var color = colors.First(c => c.StartsWidth("b")); //This will return the string with "blue"
Bot how do I do it, if I want want a random value matching the conditions? For example something like this:
Debug.log(colors.RandomFirst(c => c.StartsWidth("b"))) // Prints out black
Debug.log(colors.RandomFirst(c => c.StartsWidth("b"))) // Prints out black
Debug.log(colors.RandomFirst(c => c.StartsWidth("b"))) // Prints out blue
Debug.log(colors.RandomFirst(c => c.StartsWidth("b"))) // Prints out black
As in if there are multiple entries in the list matching the condition, i want to pull one of them randomly. It has (I need it to be) to be an inline solution. Thank you.
Random ordering then:
var rnd = new Random();
var color = colors.Where(c => c.StartsWith("b"))
.OrderBy(x => rnd.Next())
.First();
The above generates a random number for each element and sorts the results by that number.
You propbably won't notice a random results if you have only 2 elements matching your condition. But you can try the below sample (using the extension method below):
var colors = Enumerable.Range(0, 100).Select(i => "b" + i);
var rnd = new Random();
for (int i = 0; i < 5; i++)
{
Console.WriteLine(colors.RandomFirst(x => x.StartsWith("b"), rnd));
}
Output:
b23
b73
b27
b11
b8
You can create an extension method out of this called RandomFirst
:
public static class MyExtensions
{
public static T RandomFirst<T>(this IEnumerable<T> source, Func<T, bool> predicate,
Random rnd)
{
return source.Where(predicate).OrderBy(i => rnd.Next()).First();
}
}
Usage:
var rnd = new Random();
var color1 = colors.RandomFirst(x => x.StartsWith("b"), rnd);
var color2 = colors.RandomFirst(x => x.StartsWith("b"), rnd);
var color3 = colors.RandomFirst(x => x.StartsWith("b"), rnd);
If you're worried about performance, you can try this optimized method (cuts the time to half for large lists):
public static T RandomFirstOptimized<T>(this IEnumerable<T> source,
Func<T, bool> predicate, Random rnd)
{
var matching = source.Where(predicate);
int matchCount = matching.Count();
if (matchCount == 0)
matching.First(); // force the exception;
return matching.ElementAt(rnd.Next(0, matchCount));
}
In case you have IList<T>
you could also write a tiny extension method to pick a random element:
static class IListExtensions
{
private static Random _rnd = new Random();
public static void PickRandom<T>(this IList<T> items) =>
return items[_rnd.Next(items.Count)];
}
and use it like this:
var color = colors.Where(c => c.StartsWith("b")).ToList().PickRandom();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With