In C #, is there a ready-made way to create a three-way lookup table?

I have a β€œtable” in memory that might look something like this:

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

And what I want to do is quickly and efficiently search using any of the three fields. In other words, I want:

  • myTable[3]and myTable[Names.Adam]and myTable[Professions.Baker]all return{3,Names.Adam,Profession.Baker}
  • myTable[Profession.Teacher]to return both {9,Names.Bob,Profession.Teacher}, and {5,Names.Fred,Profession.Teacher}.

The table is created at runtime, in accordance with the actions of the user, and cannot be stored in the database, since it is used in sections in which it is impossible to connect to the database.

"" (hah!) 3 uber-Dictionaries, (FavoriteNumber, Name, Profession), uber- 2 , ( uber- "" Dictionary<FavoriteNumber,Profession[]> Dictionary<Profession, FavoriteNumber[]>

2 2 ( 1 2 .)

- ? , , , ( 20 ), , ...

+3
5

, ,

class Person {
    public int FavoriteNumber;
    public string Name;
    public string Profession;
}

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");

LINQ

var selectedPeople4 = from p in people
                      where p.Name == "Bob"
                      select p;

selectedPeople IEnumerable<Person>, .

+9

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]; }
}
+6

, -

public ICollection<Record> this[int] { get; }
public ICollection<Record> this[Profession] { get; }
public ICollection<Record> this[Names] { get; }

record - , .

, List.FindAll(), , .

+5

Nothing out of the box (except possibly DataTable). However, this can be done in a simpler way than what you have:

Create a class to store data:

class PersonData {
   public int FavoriteNumber;
   public string Name;
   public string Profession;
}

Then save 3 dictionaries that point to the same link:

PersonData personData = new PersonData();
Dictionary<int, PersonData> ...;
Dictionary<string, PersonData> ...;
Dictionary<string, PersonData> ...;

I would recommend encapsulating all of this in a facade class that hides implementation details.

+4
source

Could you use sqlite database as the basis? With sqlite, you even have the option of creating internal memory.

+1
source

Source: https://habr.com/ru/post/1702754/


All Articles