我有一个内存"表",可能看起来像这样:
Favorite# Name Profession --------- ---------- ------------------ 3 Names.Adam Profession.Baker 9 Names.Bob Profession.Teacher 7 Names.Carl Profession.Coder 7 Names.Dave Profession.Miner 5 Names.Fred Profession.Teacher
我想做的是使用3个字段中的任何一个进行快速有效的查找.换句话说,我想:
myTable[3]
并myTable[Names.Adam]
与myTable[Professions.Baker]
所有的回报{3,Names.Adam,Profession.Baker}
myTable[Profession.Teacher]
返回{9,Names.Bob,Profession.Teacher}
和{5,Names.Fred,Profession.Teacher}
.
该表是在运行时根据用户的操作构建的,并且不能存储在数据库中,因为它在无法保证数据库连接的部分中使用.
现在,我"简单地"(哈!)使用3个超级字典存储它,每个字符使用其中一个列(FavoriteNumber,Name,Profession)键入,并且uber-Dictionaries中的每个值包含2个字典,这些字典本身都是键入的每个剩余的列(因此"名称"超级字典中的值属于类型Dictionary
和Dictionary
这需要2个字典中的2个查找,以及数组的另一个遍历(通常包含1或2个元素.)
任何人都可以提出更好的方法吗?我不介意花费额外的内存,因为表可能很小(不超过20个条目)但我愿意牺牲一点CPU来使它更容易维护代码......
然而,并不是真的使用字典,但是如果你创建这样的类的集合
class Person { public int FavoriteNumber; public string Name; public string Profession; }
您可以使用LINQ搜索集合.
IListpeople = /* my collection */; var selectedPeople = people.Where(p => p.FavoriteNumber = 3); var selectedPeople2 = people.Where(p => p.Name == "Bob"); var selectedPeople3 = people.Where(p => p.Profession = "Teacher");
或者如果您更喜欢普通的LINQ语法
var selectedPeople4 = from p in people where p.Name == "Bob" select p;
这些selectedPeople
变量中的每一个都将被输入IEnumerable
,您可以使用循环来搜索它们.
对于20行,只需使用线性扫描 - 它在各方面都是最有效的.
对于较大的集合; hzere是一种使用LINQ ToLookup
和延迟索引的方法:
public enum Profession { Baker, Teacher, Coder, Miner } public class Record { public int FavoriteNumber {get;set;} public string Name {get;set;} public Profession Profession {get;set;} } class Table : Collection{ protected void Rebuild() { indexName = null; indexNumber = null; indexProfession = null; } protected override void ClearItems() { base.ClearItems(); Rebuild(); } protected override void InsertItem(int index, Record item) { base.InsertItem(index, item); Rebuild(); } protected override void RemoveItem(int index) { base.RemoveItem(index); Rebuild(); } protected override void SetItem(int index, Record item) { base.SetItem(index, item); Rebuild(); } ILookup indexNumber; ILookup indexName; ILookup indexProfession; protected ILookup IndexNumber { get { if (indexNumber == null) indexNumber = this.ToLookup(x=>x.FavoriteNumber); return indexNumber; } } protected ILookup IndexName { get { if (indexName == null) indexName = this.ToLookup(x=>x.Name); return indexName; } } protected ILookup IndexProfession { get { if (indexProfession == null) indexProfession = this.ToLookup(x=>x.Profession); return indexProfession; } } public IEnumerable Find(int favoriteNumber) { return IndexNumber[favoriteNumber]; } public IEnumerable Find(string name) { return IndexName[name]; } public IEnumerable Find(Profession profession) { return IndexProfession[profession]; } }
我认为这样做的方法是编写自己的对象
public ICollectionthis[int] { get; } public ICollection this[Profession] { get; } public ICollection this[Names] { get; }
其中record是一个包含元素的类.
在内部,你保留一个List,每个索引器都有List.FindAll()来获得你需要的东西.