3

I'm new to stack overflow and I'm learning a new language which is vb.net. I'm working on a first app that need the use of a database, and what i'm trying to do is taking every entries in a column, putting them in an array, suffle the array and then putting back the new array in the column of the database. Sort of a names in a hat application.. I don't have any code right now, I'm doing my lessons first and I do search many forums and I have already many pieces of the puzzle like the randomize array, database handling.. My problem is that I don't find any code to prevent data to get the same order after the shuffle for an example:

Let's pretend I have 4 entries in my database: Sarah, james, alex, daniel.

When suffling the array, how can I prevent sarah to comes first, and or james second, etc..

If you could just give me a point to start.. As I told you I'm starting to learn this language and I don't want you guys to write the app for me but just having a little clue will be much apreciate. I check lessons online but I'm getting a little bored with begginers course and the "hello world" first app demonstration so.. I think I'm ready for the next step!

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151

4 Answers4

0

In the first instance, why would the initial order be an invalid shuffling?

Putting that aside, the simplest method would be to clone your original list and element compare it with the result of your function and keep randomising until it isn't. Better check for 0 or 1 element lists or else you will get an infinite loop.

Dale M
  • 2,453
  • 1
  • 13
  • 21
0

In SQL compliant databases, the physical order of the rows in a table is supposed to be largely irrelevant, since you can sort on anything when you select the data out of it (the physical order in SQL Server is determined/set by the clustered index). So, in your situation, where you want to persist the sort order to the database, I would recommend adding an additional column that stores the sort index of each row.

So, for instance, when sorted in alphabetical order, the data would look like this:

Name     SortIndex
------   ---------
Sarah    3
James    2
Alex     0
Daniel   1

And when shuffled, the physical order wouldn't change, but the sort indexes would, for instance:

Name     SortIndex
------   ---------
Sarah    2
James    0
Alex     1
Daniel   3
Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
0

@Steven got a valid point. But I think you can even go without adding the SortIndex, because you can shuffle results directly in your query, like this (assuming your backend is MSSQL):

SELECT * FROM table1 ORDER BY NEWID()

If still necessary, here is how an array can be shuffled programmatically:

Dim a() As String = {"Sarah", "James", "Alex", "Daniel"}
Dim shuffledList As New List(Of String)
Randomize()
For i = 0 To UBound(a)
  Dim allowedValues() As String = a.Except(shuffledList).ToArray
  shuffledList.Add(allowedValues(Math.Floor(Rnd() * allowedValues.Count)))
Next

If you want to make sure original order is not repeated for any of the elements, use this code instead:

Dim a() As String = {"Sarah", "James", "Alex", "Daniel"}
Dim ub As Integer = UBound(a)
Dim shuffledList As New List(Of String)
Randomize()
For i = 0 To ub
  Dim allowedValues() As String = a.Except(shuffledList).Except({a(i)}).ToArray
  Dim randomValue As String
  If i = ub - 1 And allowedValues.Contains(a(ub)) Then
    randomValue = a(ub)
  Else
    randomValue = allowedValues(Math.Floor(Rnd() * allowedValues.Count))
  End If
  shuffledList.Add(randomValue)
Next

Here the most important part is where the item before the last one is forced to be the last item, if the last item was not already picked. This is to make sure last item goes somewhere except the last position, otherwise there is nothing to pick from in the last step. Overall, the sequence appears to be randomly sorted and it's guaranteed that item #1 will not be #1, #2 will not be #2 etc. The algorithm always ends in N steps, where N is the number of items.

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
  • I think you can't explain better than that! Yeah the problem of the last item being the last choice I knew of it, the best way to deal with it is to make the script recognize that this error is happening and then simply cancel everything and startover again until good results. With an array of 3-4 entries it can happen often but on larger array it should not be a problem. Thank you very much Neolisk your help is much appreciated now I have a point to start! – Alexandre Dumais Dec 02 '12 at 23:42
  • I'm still trying to upvote you're answer with my reputation being now 18 but it's still show me I need 15 to vote.. Well you can't complaint I didn't try :S – Alexandre Dumais Dec 02 '12 at 23:49
  • @AlexandreDumais: might be a bug - you can ask on meta.stackoverflow. But I suggest you wait 24hr to make sure their servers are updated and try again. – Victor Zakharov Dec 03 '12 at 00:29
0

Thanks for your answers. I already did that script in another language, the way I achieve it is pretty simple:

Taking the same array: Sarah, James, Alex, Daniel;

I would duplicate the array;

Then every entries in the first array would pick a random entry in the second one; Sarah would go first - if she doe's pick her own name, cancel it then pick again until she pick another name;

Then retire the picked name from the second array;

Then repeat every step with the second name, third...

All this done by a loop of course.

Maybe all this could be achieve very simply in vb.net but I'm pretty sure ( without knowing much of it) that there is no "Ramdomize.PreventSameSortIndexOrder" kind of function in vb.net ;). I understand what Steven was demonstrating but could you explain me how this way it can prevent the Index IDs to come back to the same place after the suffle? I was learning to handle MS Access database with VB but if SQL is better for some reason then it won't be a problem to switch. @Neolisk Could you tell me more about this command you wrote:

SELECT * FROM table1 ORDER BY NEWID()

Thanks all!

  • 1
    You should write your questions as comments to respective answerers. Otherwise you risk to remain unanswered. If some answers were helpful, you should upvote them. If one actually solved your problem, you should accept it as an answer to your question. Regarding `ORDER BY NEWID()`, it allows you to sort results of any query randomly. [This is how it works](http://stackoverflow.com/questions/4979799/order-by-newid-how-does-it-work). – Victor Zakharov Dec 02 '12 at 17:32
  • I'll remember that but I can't upvote answers until I get 15 reputation so... I red the post you linked and will try to start some research on it, I'm not sure to understand everything yet (yeah I am THAT new to all this) but at least it's a point to start so thank you all for your helps! – Alexandre Dumais Dec 02 '12 at 21:35
  • Now you have 18 rep - feel free to upvote everything you like. :) – Victor Zakharov Dec 02 '12 at 21:59