-1
List<KeyValuePair<string, bool>> temp = AnArray.Where(p => !p.Value).ToList();
var randomItem = temp.ElementAt(rand.Next(0, temp.Count - 1)).Key;

The code above is the way im currently doing it. but the .ToList() and kind of the .Where() aswell is using quite a bit of CPU in my workflow.

Is there any unique way to randomly select 1 element from an enumerable using the least CPU as possible perhaps without doing a ToArray/ToList and possibly without a Random() either?

Ma Dude
  • 477
  • 1
  • 5
  • 17
  • 2
    Enumerable means you can enumerate the collection; you can create an enumerable that just calls console.ReadLine. If you want to use an index, you need a data structure that supports indexing, like a list. – BurnsBA Sep 24 '18 at 12:14
  • If you are having performance issues, it might make more sense to have two lists (one for each bool value). Then you don't have to filter (with where) and don't have to convert to a list. – BurnsBA Sep 24 '18 at 12:27
  • @BurnsBA Yeah makes sense, no idea why I went the .Where() route originally (Probably for thread-safe ness) but regardless I have separated the 2 and its working a lot better but I still feel room for improvement to it – Ma Dude Sep 24 '18 at 12:50
  • Sorting the enumerable using https://stackoverflow.com/questions/9361470/random-order-of-an-ienumerable would **technically** solve your issue since it avoids counting or casting. It will still be slow (since it needs to iterate the entire enumerable, calc a random number for each of them and store the entire enumerable and the random numbers) but worth considering. To massively reduce the cost of storing the entire enumerable), use `MaxBy` instead of `OrderBy`. https://github.com/morelinq/MoreLINQ/blob/master/MoreLinq/MaxBy.cs https://www.nuget.org/packages/morelinq/ – mjwills Sep 24 '18 at 13:09
  • Did my suggestion work for you @MaDude? – mjwills Sep 24 '18 at 14:11
  • 1
    You can use this interesting [answer from @JonSkeet](https://stackoverflow.com/a/648240/2557128) to process the `IEnumerable` once, instead of allocating and counting and then indexing, but I am not sure it will be faster. – NetMage Sep 24 '18 at 21:10

1 Answers1

-2

you can avoid all of this by using .Skip()

so you end up with :

var item = AnArray.Where(p => !p.Value).Skip(rand.Next(0, temp.Count - 1)).First().Key;

Frank
  • 1
  • 1
  • 1
    Right I knew about this too but you need to realize I need to still count the .Where array so its basically just a worse .ElementAt – Ma Dude Sep 24 '18 at 12:49