0

I have the object:

public class Object{
    public String ID{get;set;}
} 

And my software receive a List:

List<Object> objs = new List<Object>();
objs.add(new Object{ID = "1"});
objs.add(new Object{ID = "2"});
objs.add(new Object{ID = "3"});
objs.add(new Object{ID = "4"});

And then I randomize it:

objs = objs.OrderBy(a => Guid.NewGuid()).ToList();
Debug.WriteLine(objs.ID);
// 1 4 2 3

If I execute objs.OrderBy(a => Guid.NewGuid()).ToList(); i'm going to receive another random sequence // 3 2 4 1.

I need to pass a "seed"(a integer number) and randomize about this number, for example, if I pass the seed 1 I receive // 3 2 4 1, when I execute the number 1 again i need to receive the same order // 3 2 4 1.

There is a way to do it in c#?

Edit: The object above is just a example, the real case i need to randomize the following object:

public class Object{
    public Int ID{get;set;}
    public String ImageTitle{get;set;}
    public String ImageDescription{get;set;}
    public String Url {get;set;}
} 
Leonardo Bonetti
  • 197
  • 1
  • 10
  • 1
    If you use random instead of GUID you'll have more control over this. – doctorlove Mar 14 '19 at 12:25
  • But, bear in mind that `OrderBy` is not stable in the (unlikely) event that your `Random` gives you the same number twice – canton7 Mar 14 '19 at 12:27
  • how can i use random in a list of object? – Leonardo Bonetti Mar 14 '19 at 12:27
  • The numbers is just a example, the list of objects that i have to randomize is more complex did you understand? I dont need just numbers, but i need to randomize a list of objects with more than one field for example. – Leonardo Bonetti Mar 14 '19 at 12:30
  • I will edit the question – Leonardo Bonetti Mar 14 '19 at 12:30
  • 1
    *Fisher–Yates shuffle* https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle is a standard algorithm which is *fast* `O(n)` guarantees *unbiased permutation*. Sorting by `Random` or `Guid` *doesn't* – Dmitry Bychenko Mar 14 '19 at 12:36
  • @DmitryBychenko doesn't it? Bear in mind that `OrderBy` generates the key for each element *once*, and then uses the key to sort the items. It will *not* create a new random number for each element whenever it needs to compare it. Therefore I would expect it to be unbiased. – canton7 Mar 14 '19 at 12:45
  • Possible duplicate: https://stackoverflow.com/questions/273313/randomize-a-listt – Dmitry Bychenko Mar 14 '19 at 12:45
  • Guids are **not** guaranteed to be random, just unique. They shouldn't be used when you want randomness. – Enigmativity Apr 04 '19 at 08:33
  • @DmitryBychenko - `OrderBy` is unbaised when used with `Random`. It's not `O(n)` though, I agree with that. – Enigmativity Apr 04 '19 at 08:34

2 Answers2

3

Not with GUID, but with Random it's not only possible but easy:

var seed = 123;
var r = new Random(seed);
objs = objs.OrderBy(o => r.Next()).ToList();

You can see a live demo on rextester.

Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • Bear in mind that this doesn't work in the unlikely event that `Random.Next` gives you the same number twice. – canton7 Mar 14 '19 at 12:46
  • @canton7 the `Next()` method returns a random int value between 0 and 2147483647 - unlikely is an understatement. – Zohar Peled Mar 14 '19 at 13:07
  • I think I was wrong anyway -- the sort won't be *stable* in this case, but it will be *deterministic*. Given that the order of the input sequence needs to be constant anyway, I think unstable but deterministic is fine. – canton7 Mar 14 '19 at 13:15
  • @canton7 - The sort done this way is stable. The underlying sort algorithm only computes the random number once per element of the source and continues to use that for comparison. – Enigmativity Apr 04 '19 at 04:10
  • @Enigmativity I was talking specifically about the case where two items are given the same random number. "Stable" means that if two items compare as equal, then they will have the same order in the output as they did in the input. It turns out that OrderBy was made stable anyway - that wasn't always the case. – canton7 Apr 04 '19 at 07:58
  • @canton7 - "if two items compare as equal, then they will have the same order in the output as they did in the input" - that's what I meant by stable. I believe `OrderBy` has been stable since version 1. – Enigmativity Apr 04 '19 at 08:24
  • @Enigmativity See e.g. https://stackoverflow.com/a/1209939/1086121 . That used to be a big gotcha - List.Sort was stable, but OrderBy wasn't. – canton7 Apr 04 '19 at 08:26
  • @canton7 - Not according to https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderby?view=netframework-3.5 - that shows it as stable on the first release. – Enigmativity Apr 04 '19 at 08:27
  • Confirmed on archive.org's copy of the original doc. Seems I was mislead by Joe's book! On reading Jon's review in more detail, looks like it was the spec that changed, before .NET 3.5 was released. – canton7 Apr 04 '19 at 08:41
0

Use this method and cache randomized arrays and serve it again. easy.

    private Dictionary<int, List<Object>> randoms=new Dictionary<int, List<Object>>();

    private List<Object> GetRandom(List<Object> objs,int? seed)
    {
        if (seed == null)
        {
            return objs.OrderBy(a => Guid.NewGuid()).ToList();
        }
        else
        {
            if (!randoms.ContainsKey(seed.Value))
            randoms[seed.Value] = objs.OrderBy(a => Guid.NewGuid()).ToList();

            return randoms[seed.Value];
        }
    }

Example call GetRandom(objs,null) will always randomize it. If you call it with number GetRandom(objs,1) he will serve old randomized array.

wikiCan
  • 449
  • 3
  • 14