0

Using .net core so I do not have access to System.Drawing. I have a list of 865 color names and their hex equivalent (in 0x format). I will NEVER need to modify list, I only need to be able to quickly search the list from Either column (could be searching the name or the hex). Names are easy and in alphabetical order, but Hex's what they are. I want it to quickly find the counterpart searching either way? what would be the best approach to create the data structure, and what search methods would you use?

I was researching http://cc.davelozinski.com/c-sharp/fastest-collection-for-string-lookups

It shows some interesting data, but it only searches from a single column so not quite what i'm looking for. Sorted list seems the way to go if I was only using color names as the key value, but Hex is throwing my off a bit.

Example list:

Air superiority blue    0x72A0C1 
Alabama Crimson     0xA32638 
Alice blue  0xF0F8FF 
Alizarin crimson    0xE32636 
Alloy orange    0xC46210 
Almond  0xEFDECD 
Amaranth    0xE52B50 
Amber   0xFFBF00 
svick
  • 236,525
  • 50
  • 385
  • 514
HappyCamp
  • 1
  • 4

2 Answers2

4

If you have a static list (changes are so infrequent that they're negligible), and you need immediate, ultra-high-speed access either way, you can use one of many simple C# features, I'm going to outline 2 major options: switch or Dictionary, however you need two of each for the fastest method.

You can use a programme to generate the code for you, but the examples are as follows:

Switch / Case

The first example is easy, build two methods, GetHexFromName and GetNameFromHex, and a switch statement in them.

public static int GetHexFromName(string name)
{
    switch (name)
    {
        case "Amaranth":
            return 0xE52B50;
        case "Amber":
            return 0xFFBF00;
        // Remaining 863 colors
        default:
            throw new ArgumentException();
    }
}

public static string GetNameFromHex(int hex)
{
    switch (hex)
    {
        case 0xE52B50:
            return "Amaranth";
        case 0xFFBF00:
            return "Amber";
        // Remaining 863 colors
        default:
            throw new ArgumentException();
    }
}

Easy enough. You can build a quick tool that could generate the code for you, Roslyn would probably make it even easier.

You would call this as GetHexFromName(colorName).

Dictionaries

This is probably the method I would go along with, as access reads a bit better.

public static readonly ReadOnlyDictionary<string, int> Hex = new ReadOnlyDictionary<string, int>(new Dictionary<string, int> {
    ["Amber"] = 0xE52B00,
    ["Amaranth"] = 0xFFBF00,
    // Remaining 863
});

public static readonly ReadOnlyDictionary<int, string> Name = new ReadOnlyDictionary<int, string>(new Dictionary<int, string> {
    [0xE52B00] = "Amber",
    [0xFFBF00] = "Amaranth",
    // Remaining 863
});

This reads as Hex[colorName].

It's easy to adjust either of these to put the hex in string format. The ReadOnlyDictionary is in the System.Collections.ObjectModel namespace in the System.Collections.dll library. The .NET Core version might not have that, so you may need to omit that from your code. Just trust that no one will call any methods on the Dictionary types. I've also written this for C#6.0 syntax - you may need to alter that for your environment.


These are going to be your fastest options, especially if the list doesn't change frequently (or at all). The only problem is maintainability, but usually you sacrifice one of: maintainability, performance, simplicity. Here we sacrifice maintainability a bit, but we get a lot of performance.

Also, order shouldn't matter much in either of these cases: in the switch option the compiler will generate the optimal code (we hope), in the Dictionary option the JITter and Dictionary implementation will optimize the structure. Reading from either of these should be fast.

Der Kommissar
  • 5,848
  • 1
  • 29
  • 43
  • 2
    @MickyD Switch and [Dictionary access](https://msdn.microsoft.com/en-us/library/9tee9ht2(v=vs.110).aspx) are documented in the framework as O(1). (Switch might not be documented as O(1) but it builds a jump table which is literally one instruction with O(1) on most platforms.) – Der Kommissar Apr 12 '17 at 06:26
  • Although ugly, I see what you mean. in this case since there is really no editing after its done it makes the most sense. I like the Dictionary method you suggested so I will go that route. This is one file I hope I never have to open again after its done! *note* - .NET Core does have Collections and we can use ObjectModel. – HappyCamp Apr 12 '17 at 13:59
  • Please mark @EBrown as the answer here. This was extremely easy to set up, and very quick. I went with the readonly dictionary, and its working like a champ! Thanks! – HappyCamp Apr 18 '17 at 13:49
-1

For less than 1000 rows - any way you decide to do this will be negligible in computational power -

1) Old-fashioned dictionary (probably the easiest way) - hxxps://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx

Not the prettiest way: Create a static class in your application with a datatable: hxxps://msdn.microsoft.com/en-us/library/system.data.datatable(v=vs.110).aspx

You can hard-code these values when the class is instantiated, or pull them from a separate data source (if you're really concerned about performance, hard code the values).

Using this method you'll be able to return the entire row using a select statement: hxxps://msdn.microsoft.com/en-us/library/det4aw50(v=vs.110).aspx

ex:

DataTable Table = class.datatable();
// Datatable class created with 2 columns: color,hex
string expression = "color = Almond"; //or "hex = 0xEFDECD"
DataRow[] foundRows;
foundRows = Table.Select(expression);

Foundrows[0] will equal almond foundRows[1] will equal the hex value

You could do the same thing with a static JSON object or array as well and use LINQ to search it: hxxp://newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm

I'd be interested to compare performance between the three, but for less than 1000 rows - without actually doing the performance test on the full dataset...I'm going to go out on a limb and say that the easiest and fastest performance-wise will be the dictionary.

Note: My ranking is below 10 - you'll need to replace 'hxxp' with 'http' in the links.

JTStuedle
  • 161
  • 1
  • 2
  • There is no DataTable or DataRow in .NET Core – Digicoder Apr 13 '17 at 03:25
  • https://www.nuget.org/packages/DataTables.AspNet.Core/ - I beg to differ. Though not a "Microsoft" published package, there are options available to make datatables work in .NET Core :) - though I didn't catch the word 'core' in the first sentence - dang the ADD. – JTStuedle Apr 14 '17 at 14:56