- Home /
Dictionary, List, Hashtable - Best Practices
Hello,
Right now I have a Hashtable storing my building locations (in grid format). I realized I needed to be able to find buildings only on a certain Y value (my key is a Vector2, value is GameObject), and I don't want to iterate through the whole Hashtable to find a handful of entries with a desired Y value. I use this for grid based-position checking, and I imagine it could get pretty darn big.
So I made a Dictionary< float, List< GameObject >>;
to store the Y level and all the buildings in it. That way I can grab a list of the desired Y objects right away.
Is this the most efficient way to do it? Should I rewrite my code to use only the Dictionary, and iterate through my list to check my grid based positioning?
There could be thousands of entries in these arrays.
Tuples?
Answer by whydoidoit · Mar 05, 2014 at 07:55 AM
So keying an array off a float (or a vector of floats) sounds pretty dangerous to me - you know float inaccuracies and everything. Could you make it fixed point by multiplying Y by a power of 10 and converting to an int?
You could reduce the problem space by querying the keys of your Vector2 dictionary for the correct Y and then iterate the lists it produces. Though the approach of having two lookups seems OK to me - it all depends on the number of times you will do each thing.
Or you could (while please paying heed to my concerns over any kind of float as a dictionary key) use something primarily keyed off Y and then off X in your vector2:
Dictionary<float, Dictionary<float, List<GameObject>>> lookup;
Lookup using
var list = lookup[vector.y][vector.x];
If you want a dictionary that doesn't keep throwing nulls and auto creates the things you need you could use this class which will auto create the sub elements if they are missing:
using System;
public class Index<T$$anonymous$$, TR> : Dictionary<T$$anonymous$$, TR> where TR : new()
{
public virtual TR Create()
{
return new TR();
}
public override TR this[T$$anonymous$$ index]
{
get
{
TR value;
if (TryGetValue(index, out value))
{
return value;
}
var ret = Create();
base[index] = ret;
return ret;
}
set
{
if (Setting != null)
{
TR current = default(TR);
TryGetValue(index, out current);
Setting(index, current, value);
}
base[index] = value;
}
}
public event Action<T$$anonymous$$, TR, TR> Setting;
}
Thank you, the example you provided should work for both tables. I'll definitely key it with an int ins$$anonymous$$d.
When trying to use your class I get a cannot override because of sealed System.Collections.Generic
Good point. I'll post the dictionary class I use as the base. (It's the decompiler dictionary from .net
No I'm wrong about that - I am inheriting from Dictionary in my code but I'm building it as an external DLL. What are you building it with (through Unity? externally?) If it's any use to you I'll post that built DLL which contains Index (and also DefaultDictionary which returns the default value rather than an exception when a key is missing)?
Your answer
Follow this Question
Related Questions
How can I create a tree like list/array structure? 0 Answers
Dictionary Keys to Stack Enemy Types 1 Answer
Dictionary key exists but corresponding value pair is non-existent 0 Answers
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers