我有一个内存"表",可能看起来像这样:
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
Run Code Online (Sandbox Code Playgroud)
我想做的是使用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<FavoriteNumber,Profession[]>
和Dictionary<Profession, FavoriteNumber[]>
这需要2个字典中的2个查找,以及数组的另一个遍历(通常包含1或2个元素.)
任何人都可以提出更好的方法吗?我不介意花费额外的内存,因为表可能很小(不超过20个条目)但我愿意牺牲一点CPU来使它更容易维护代码......
然而,并不是真的使用字典,但是如果你创建这样的类的集合
class Person {
public int FavoriteNumber;
public string Name;
public string Profession;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用LINQ搜索集合.
IList<Person> people = /* 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");
Run Code Online (Sandbox Code Playgroud)
或者如果您更喜欢普通的LINQ语法
var selectedPeople4 = from p in people
where p.Name == "Bob"
select p;
Run Code Online (Sandbox Code Playgroud)
这些selectedPeople
变量中的每一个都将被输入IEnumerable<Person>
,您可以使用循环来搜索它们.
对于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<Record>
{
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<int, Record> indexNumber;
ILookup<string, Record> indexName;
ILookup<Profession, Record> indexProfession;
protected ILookup<int, Record> IndexNumber {
get {
if (indexNumber == null) indexNumber = this.ToLookup(x=>x.FavoriteNumber);
return indexNumber;
}
}
protected ILookup<string, Record> IndexName {
get {
if (indexName == null) indexName = this.ToLookup(x=>x.Name);
return indexName;
}
}
protected ILookup<Profession, Record> IndexProfession {
get {
if (indexProfession == null) indexProfession = this.ToLookup(x=>x.Profession);
return indexProfession;
}
}
public IEnumerable<Record> Find(int favoriteNumber) { return IndexNumber[favoriteNumber]; }
public IEnumerable<Record> Find(string name) { return IndexName[name]; }
public IEnumerable<Record> Find(Profession profession) { return IndexProfession[profession]; }
}
Run Code Online (Sandbox Code Playgroud)
我认为这样做的方法是编写自己的对象
public ICollection<Record> this[int] { get; }
public ICollection<Record> this[Profession] { get; }
public ICollection<Record> this[Names] { get; }
Run Code Online (Sandbox Code Playgroud)
其中record是一个包含元素的类.
在内部,你保留一个List,每个索引器都有List.FindAll()来获得你需要的东西.