How to create a unique random character sequence in C #?

I use the URL reduction feature in my application to provide my users with shorter alternative URLs that can be used on Twitter. The bottom line is to be independent of the declining services offering the same service, and to include it as a function of my web application.

What is the best way to create a unique random character sequence of about 6 characters? I plan to use this as an index for items in my database that will have alternate URLs.

Edited by:

This feature will be used on the job board website, where each new job posting will receive its own URL with a header plus a shorter one that will be used on Twitter. However, the total number of unique 6 char combinations will be more than enough for a long time.

+6
string c # random
source share
10 answers

Do you really need "random" or "unique"?

The uniqueness is extremely simple - just paste the URL into the database and convert the sequential identifier for this entry to the base number -n, which is represented by your selected character set.

For example, if you want to use only [AZ] in your sequence, you convert the record identifier to base number 26, where A = 1, B = 2, ... Z = 26. The algorithm is recursive div26 / mod26, where the private is mandatory character, and the remainder is used to calculate the next character.

Then, when you get the URL, you perform the inverse function, which is to convert the base 26 number back to decimal. Run SELECT URL WHERE ID = decimal and you're done!

EDIT:

private string alphabet = "abcdefghijklmnopqrstuvwxyz"; // or whatever you want. Include more characters // for more combinations and shorter URLs public string Encode(int databaseId) { string encodedValue = String.Empty; while (databaseId > encodingBase) { int remainder; encodedValue += alphabet[Math.DivRem(databaseId, alphabet.Length, out remainder)-1].ToString(); databaseId = remainder; } return encodedValue; } public int Decode(string code) { int returnValue; for (int thisPosition = 0; thisPosition < code.Length; thisPosition++) { char thisCharacter = code[thisPosition]; returnValue += alphabet.IndexOf(thisCharacter) * Math.Pow(alphabet.Length, code.Length - thisPosition - 1); } return returnValue; } 
+3
source share

The easiest way to make unique sequences is to do it sequentially, that is: aaaaaa aaaaab aaaaac ... They are not necessarily the most beautiful, but they guarantee uniqueness for the first 12230590463 sequences (provided that you used az and AZ as unique characters). If you need more urls you need to add a seventh char.

However, they are not random sequences. If you are doing random, just select a random char from 48, 6 times. However, you will need to check the existing database for the "used" sequences, as you will have a better chance of a collision.

+3
source share

I would use the autonumber system and create an algorithm for generating keys. those. 1 = a, 2 = b, 27 = aa, etc.

Can you use autostart database to ensure that your url is unique and you can calculate the url, maybe in sproc in the database or at the business level?

In addition, you can now index an increasing number, which is cheap, and DBs are optimized for use and hashed as primary / foreign keys, as opposed to a random variable-length string.

+2
source share

The usefulness of a random generator is limited by the fact that users cannot connect random URLs to find things with which they should not have a link. If this is not your goal, then sequential identifiers should work fine. If you just do not want to give users the impression that they are using "baby" technology (when they see that their job announcement is No. 000001), why not start the sequence at some arbitrary value?

+1
source share

When you indicate that “the total number of unique 6 char combinations will be more than enough for a long time” for your random generation, did you take into account the paradoxical birthday in your calculations? This is usually the mistake of any attempt to create random identifiers within a range that is only an order of magnitude or less than the expected range that will be needed.

To create truly random identifiers, you need to create a loop that generates a new random value, checks to see if that value has already been used, and then iterates the loop if necessary. The birthday paradox means that you quickly get to the point where many of the generated values ​​are already in use (despite the fact that they consume only part of the entire range), which causes the program to become slower and slower over time until it picks up thousands of attempts (and database searches) to generate each identifier.

I would suggest you move on to the idea of ​​coding consecutive identifiers. To avoid the problem that users can simply increase / decrease the value in the URL to “explore”, you can use a combined bit offset and an alternative ordered list of letters (use 1 = t instead of 1 = a, 2 = b , 2 = j, etc.).

+1
source share

Thinking about it more here is an idea.

You can start with the key table by increasing the characters AAAAAA - ZZZZZZ.

Then make a random selection from this table each time you insert a new URL and remove from the available keys.

Thoughts?

For random selection try link

 Select a random row with MySQL: SELECT column FROM table ORDER BY RAND() LIMIT 1 Select a random row with PostgreSQL: SELECT column FROM table ORDER BY RANDOM() LIMIT 1 Select a random row with Microsoft SQL Server: SELECT TOP 1 column FROM table ORDER BY NEWID() Select a random row with IBM DB2 SELECT column, RAND() as IDX FROM table ORDER BY IDX FETCH FIRST 1 ROWS ONLY Thanks Tim Select a random record with Oracle: SELECT column FROM ( SELECT column FROM table ORDER BY dbms_random.value ) WHERE rownum = 1 
0
source share
0
source share

Instead of saving a table of all possible values, just save the table of values ​​you used. Use a random function to generate 6 random values, from 1 to 26, output a string from it and save it in an array or table. If it already exists, you can (a) generate another row or (b) go through the table to the next available (missing) 6-letter row and use this value. (b) will be more effective as the table is filled.

0
source share

Following the idea of ​​Reed Copsi's answer, I present the following code:

 class IDGetter { private StringID ID = new StringID(); public string GetCurrentID() { string retStr = ""; if (ID.char1 > 51) id.char1 = 0; if (ID.char2 > 51) id.char2 = 0; if (ID.char3 > 51) id.char3 = 0; if (ID.char4 > 51) id.char4 = 0; if (ID.char5 > 51) id.char5 = 0; if (ID.char6 > 51) throw new Exception("the maximum number of id has been reached"); return ToIDChar(ID.char1) + ToIDChar(ID.char2) + ToIDChar(ID.char3) + ToIDChar(ID.char4) + ToIDChar(ID.char5) + ToIDChar(ID.char6) id.char1++; } public void SetCurrentID(StringID id) //for setting the current ID from storage or resetting it or something { this.ID = id; } private const string alphabet = "abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static string ToIDChar(int number) { if (number > 51 || number < 0) { throw new InvalidArgumentException("the number passed in (" + number + ") must be between the range 0-51"); } return alphabet[number]; } } public struct StringID { public int char1 = 0; public int char2 = 0; public int char3 = 0; public int char4 = 0; public int char5 = 0; public int char6 = 0; } 

You may need a method to store the current identifier, but this should work.

0
source share

I used this to make something very similar. I did not have to worry about the speed of it, as this would be a rarely used event and table. But if necessary, you can increase the line.

 /// Generates a string and checks for existance /// <returns>Non-existant string as ID</returns> public static string GetRandomNumbers(int numChars, string Type) { string result = string.Empty; bool isUnique = false; while (!isUnique) { //Build the string result = MakeID(numChars); //Check if unsued isUnique = GetValueExists(result, Type); } return result; } /// Builds the string public static string MakeID(int numChars) { string random = string.Empty; string[] chars = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; Random rnd = new Random(); for (int i = 0; i < numChars; i++) { random += chars[rnd.Next(0, 35)]; } return random; } /// Checks database tables based on type for existance, if exists then retry /// <returns>true or false</returns> private static bool GetValueExists(string value, string Type) { bool result = false; string sql = ""; if (Type == "URL") { sql = string.Format(@"IF EXISTS (SELECT COUNT(1) FROM myTable WHERE uniqueString = '{0}') BEGIN SELECT 1 END ELSE BEGIN SELECT 0 END ", value); } //query the DB to see if it in use result = //ExecuteSQL return result; } 
0
source share

All Articles