2009-02-05 4 views
3

내가 메모리 "테이블"그 힘이 같은 모양이 있습니다C#에서는 3-way 룩업 테이블을 만들 수있는 out-of-the-box 방법이 있습니까?

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]
  • myTable[Profession.Teacher]{3,Names.Adam,Profession.Baker}{9,Names.Bob,Profession.Teacher}{5,Names.Fred,Profession.Teacher} 모두를 반환하는 반환합니다.

테이블은 런타임 중에 사용자의 작업에 따라 작성되며 데이터베이스 연결을 보장 할 수없는 섹션에서 사용되기 때문에 데이터베이스에 저장할 수 없습니다.

지금은 (즐겨 찾기 번호, 이름, 직업) 중 하나의 열을 사용하여 각각 3 개의 uber-Dictionaries와 2 개의 사전을 보유한 uber-Dictionaries의 각 값을 사용하여 "간단히"(hah!) 저장합니다. ("Name"uber-dictionary의 값은 Dictionary<FavoriteNumber,Profession[]>이고 Dictionary<Profession, FavoriteNumber[]>

입니다.) 두 개의 사전에는 두 개의 조회가 필요하며 일반적으로 1 또는 2 요소).

누구든지이 작업을 수행하는 더 좋은 방법을 제안 할 수 있습니까? 테이블이 작기 때문에 메모리를 추가로 사용하지 않아도됩니다. 0 개 항목)하지만 난 그게 더 쉽게 유지 보수 코드를 만들기 위해 약간의 CPU를 희생 기꺼이 ...이

class Person { 
    public int FavoriteNumber; 
    public string Name; 
    public string Profession; 
} 
같은 클래스의 컬렉션을 만들 경우
+1

해야하지 myTable에 의한 첫 번째 예 [3]? – plinth

+0

20 행의 경우 선형 검색을 사용하십시오. 사전보다 빠릅니다. –

+0

@plinth - 꽤 정확한 – scraimer

답변

9

정말 그러나 사전을 사용하지만,하지

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>로 입력을 받고 그들을 통해 검색하는 루프를 사용할 수 있습니다를 원하는 경우.

+0

이 단점은 표현을 드러내는 것입니다. IList가 충분하지 않으면 리팩터링하는 것이 고통 스럽습니다. – plinth

+0

+1, * 정확히 * 그냥 입력했는데 – LukeH

+1

그리고 IList <>이기 때문에 요청한 OP로 인덱스별로 조회를 수행 할 수도 있습니다. 예 : people [0] = {3, "Adam", "Baker"} 등 – LukeH

5

나는이 작업을 수행하는 방법이 기록은 당신의 요소를 보유하는 클래스가

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

을 가지고 자신의 개체를 작성하는 것입니다 생각합니다.

내부적으로 목록을 유지하고 각 인덱서는 필요한 것을 얻기 위해 List.FindAll()을 수행합니다.

+1

OP는 20 행을 나타 내기 때문에 모든면에서 가장 효율적인 옵션이다. –

1

sqlite 데이터베이스를 백업으로 사용할 수 있습니까? sqlite를 사용하면 in-memory db를 구축 할 수 있습니다.

4

Out-of-the-box (아마도 DataTable 제외)는 없습니다.그럼에도 불구하고, 당신이있어 어떤 것을 더 간단한 방법으로 수행 할 수 있습니다

은 데이터를 보유하는 클래스를 만듭니다

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

을 다음 동일한 참조를 가리 3 개 사전을 유지 :

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

이 모든 것을 구현 세부 정보를 숨기는 외관 클래스에 캡슐화하는 것이 좋습니다.

6

20 행의 경우 linear scanning을 사용하십시오. 모든면에서 가장 효율적입니다.

큰 세트의 경우; LINQ의 ToLookup 및 지연 색인을 사용하여 접근 방식은 hzere입니다 :

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

선형 측정이 내 작은 측정을위한 최선의 방법이라고 생각할 것이다. 가장 좋은 방법은 "코드를 관리하는 데 소요 된 시간"을 포함하는 것입니다. – scraimer

관련 문제