Reputation: 33
I've been exploring dynamic dictionaries as a potential solution to associating multiple strings with a single 'ID' string. What I need to do is assign a series of 4-letter text strings to a key that is also a 4-letter text string (each string is unique with a range of AAAA-ZZZZ).
The keys are 4-letter text strings like: "AAAA", "AAGB", etc. Each key can hold multiple 4-letter text strings: "ACFE", "AAFE", etc.
The goal is to select a key and then randomly select one of the dynamic values inside it. My current setup for testing is as follows:
// Dynamic objects
dynamic d1 = new System.Dynamic.ExpandoObject();
dynamic d2 = new System.Dynamic.ExpandoObject();
dynamic d3 = new System.Dynamic.ExpandoObject();
var dict = new Dictionary<string, dynamic>();
// Assign dynamic objects to the Dictionary Key
dict["AAAA"] = d1;
dict["AAGB"] = d2;
dict["ABDA"] = d3;
// Populate the dynamic object with the value(s)
dict["AAAA"].FooBar = new { i1 = "ACFE", i2 = "AAFE", i3 = "CAED", i4 = "HSGB" };
dict["AAGB"].FooBar = new { i1 = "ZZZZ", i2 = "XXXX", i3 = "CAED", i4 = "HSGB" };
dict["ABDA"].FooBar = new { i1 = "YYYY", i2 = "WWWW", i3 = "CAED", i4 = "HSGB" };
string newName = dict["ABDA"].FooBar.i1;
return newName;
That pulls through the correct string. But is there a way of setting this up so I can pull one of the values out at random instead of having to explicitly specify which value I'm after? Or should I change the approach altogether (I've done something similar to this using jagged arrays and will use that as a fallback but was curious about this dynamic dictionary as a possible alternative).
Upvotes: 1
Views: 2047
Reputation: 31
In your case, assuming you already know the types of keys and values you probably should use the Dictionary with expandable collection as value. The appropriate type is
Dictionary<string, List<string>>
Therefore, you won't get the excessive overhead from using dynamic runtime and you'd be able to push and retrieve values from List randomly just as from any collection.
Upvotes: 3
Reputation: 34431
Create numbers using Base26
class Program
{
static void Main(string[] args)
{
Base26 base26 = new Base26();
for(int i = 0; i < base26.MAX_NUM; i++)
{
Console.WriteLine(base26.ToString());
}
Console.ReadLine();
}
}
public class Base26
{
public int MAX_NUM = (int)Math.Pow(26, 4);
int current = 0;
public override string ToString()
{
byte[] base26 = new byte[4];
base26[3] = (byte)(current % 26);
base26[2] = (byte)((current / 26) % 26);
base26[1] = (byte)((current / (26 * 26)) % 26);
base26[0] = (byte)((current / (26 * 26 * 26)) % 26);
current++;
if (current == MAX_NUM) current = 0;
return string.Join("", base26.Select(x => (char)(((byte)'A') + x)));
}
}
Upvotes: 0
Reputation: 21477
If you want an immutable collection (You aren't going to be adding to the collection after the collection is created), then use a Lookup. If you need to be able to add/remove entries, then use a dictionary. I've included an example of using IGrouping, but it is the slowest for lookups since you need to iterate through until you find the key, but very efficient if you need to iterate all the keys like you want to pull a random string for every key.
Here's an example of using a Lookup:
var values = new[] {
new KeyValuePair<string,string> ("AAAA","ACFE"),
new KeyValuePair<string,string> ("AAAA","AAFE"),
new KeyValuePair<string,string> ("AAAA","CAED"),
new KeyValuePair<string,string> ("AAAA","HSGB"),
new KeyValuePair<string,string> ("AAGB","ZZZZ"),
new KeyValuePair<string,string> ("AAGB","XXXX"),
new KeyValuePair<string,string> ("AAGB","CAED"),
new KeyValuePair<string,string> ("AAGB","HSGB"),
new KeyValuePair<string,string> ("ABDA","YYYY"),
new KeyValuePair<string,string> ("ABDA","WWWW"),
new KeyValuePair<string,string> ("ABDA","CAED"),
new KeyValuePair<string,string> ("ABDA","HSGB"),
};
// Convert array to a Lookup
var lookup=values.ToLookup(k=>k.Key, v=>v.Value);
// Retrieve random string from entry "AAAA"
var entry = lookup["AAAA"];
var rand = new Random();
var max = entry.Count();
var ans = entry.Skip(rand.Next(max)).First();
Here's an example of using a Dictionary<string,List<string>>
:
var values = new[] {
new KeyValuePair<string,string> ("AAAA","ACFE"),
new KeyValuePair<string,string> ("AAAA","AAFE"),
new KeyValuePair<string,string> ("AAAA","CAED"),
new KeyValuePair<string,string> ("AAAA","HSGB"),
new KeyValuePair<string,string> ("AAGB","ZZZZ"),
new KeyValuePair<string,string> ("AAGB","XXXX"),
new KeyValuePair<string,string> ("AAGB","CAED"),
new KeyValuePair<string,string> ("AAGB","HSGB"),
new KeyValuePair<string,string> ("ABDA","YYYY"),
new KeyValuePair<string,string> ("ABDA","WWWW"),
new KeyValuePair<string,string> ("ABDA","CAED"),
new KeyValuePair<string,string> ("ABDA","HSGB"),
};
//Convert array to Dictionary<string,List<String>>
var dict = values.GroupBy(k=>k.Key)
.ToDictionary(k=>k.Key,v=>v.Select(kvp=>kvp.Value).ToList());
// Retrieve random string from entry "AAAA"
var entry = lookup["AAAA"];
var rand = new Random();
var max = entry.Count();
var ans = entry.Skip(rand.Next(max)).First();
Here's an example using IGrouping:
var values = new[] {
new KeyValuePair<string,string> ("AAAA","ACFE"),
new KeyValuePair<string,string> ("AAAA","AAFE"),
new KeyValuePair<string,string> ("AAAA","CAED"),
new KeyValuePair<string,string> ("AAAA","HSGB"),
new KeyValuePair<string,string> ("AAGB","ZZZZ"),
new KeyValuePair<string,string> ("AAGB","XXXX"),
new KeyValuePair<string,string> ("AAGB","CAED"),
new KeyValuePair<string,string> ("AAGB","HSGB"),
new KeyValuePair<string,string> ("ABDA","YYYY"),
new KeyValuePair<string,string> ("ABDA","WWWW"),
new KeyValuePair<string,string> ("ABDA","CAED"),
new KeyValuePair<string,string> ("ABDA","HSGB"),
};
//Convert array to IGrouping<string,string>
var group = values.GroupBy(k=>k.Key);
// Retrieve random string from entry "AAAA"
var entry = group.First(k=>k.Key == "AAAA");
var rand = new Random();
var max = entry.Count();
var ans = entry.Skip(rand.Next(max)).First().Value;
Upvotes: 1
Reputation: 156708
You should change your approach altogether. dynamic
is intended for circumstances where you know something about the shape of the object you're dealing with (e.g. that is has a FooBar
or i1
property), but you don't know what type it will be at compile-time (maybe it comes from an untyped language, like JavaScript or Python).
If your use case doesn't match those criteria, I'd say you're better off using Dictionaries for anything where you don't know (at compile-time) which part of the data you want (e.g. pulling values out at random), and using strong class types and interfaces for the shapes that should be known at compile-time.
Upvotes: 1