Как получить доступ к ссылочным значениям HashSet<TValue> без перечисления?

У меня есть такой сценарий, в котором сохранение памяти имеет первостепенное значение. Я пытаюсь прочитать в> 1 ГБ пептидных последовательностей в память и сгруппировать экземпляры пептидов вместе, которые имеют одну и ту же последовательность. Я храню объекты Пептид в Хэше, чтобы я мог быстро проверить на дублирование, но обнаружил, что вы не можете получить доступ к объектам в наборе, даже зная, что набор содержит этот объект.

Память действительно важна, и я не хочу дублировать данные, если это вообще возможно. (В противном случае я бы разработал свою структуру данных как: пептиды = Dictionary<string, Peptide> но это дублирует строку как в словаре, так и в классе пептидов). Ниже приведен код, показывающий, чего я хотел бы достичь:

public SomeClass {

       // Main Storage of all the Peptide instances, class provided below
       private HashSet<Peptide> peptides = new HashSet<Peptide>();

       public void SomeMethod(IEnumerable<string> files) {
            foreach(string file in files) {
                 using(PeptideReader reader = new PeptideReader(file)) {
                     foreach(DataLine line in reader.ReadNextLine()) {
                         Peptide testPep = new Peptide(line.Sequence);
                         if(peptides.Contains(testPep)) {

                            // ** Problem Is Here **
                            // I want to get the Peptide object that is in HashSet
                            // so I can add the DataLine to it, I don't want use the
                            // testPep object (even though they are considered "equal")
                            peptides[testPep].Add(line); // I know this doesn't work

                            testPep.Add(line) // THIS IS NO GOOD, since it won't be saved in the HashSet which i use in other methods.

                         } else {
                            // The HashSet doesn't contain this peptide, so we can just add it
                            testPep.Add(line);
                            peptides.Add(testPep);
                         }
                     }   
                 }
            }
       }
}

public Peptide : IEquatable<Peptide> {
     public string Sequence {get;private set;}
     private int hCode = 0;

     public PsmList PSMs {get;set;}

     public Peptide(string sequence) {
         Sequence = sequence.Replace('I', 'L');
         hCode = Sequence.GetHashCode();             
     }

     public void Add(DataLine data) {
         if(PSMs == null) {
             PSMs = new PsmList();
         } 
         PSMs.Add(data);
     }

     public override int GethashCode() {
         return hCode;
     }

     public bool Equals(Peptide other) {
         return Sequence.Equals(other.Sequence);
     }
}

public PSMlist : List<DataLine> { // and some other stuff that is not important }

Почему HashSet не позволите мне получить ссылку на объект, который содержится в HashSet? Я знаю, что люди будут пытаться сказать, что если HashSet.Contains() возвращает true, ваши объекты эквивалентны. Они могут быть эквивалентны с точки зрения значений, но мне нужно, чтобы ссылки были одинаковыми, так как я храню дополнительную информацию в классе пептидов.

Единственное решение, которое я нашел, это Dictionary<Peptide, Peptide> в котором и ключ, и значение указывают на одну и ту же ссылку. Но это кажется липким. Есть ли другая структура данных для этого?

2 ответа

Решение

В основном вы могли бы переопределить HashSet<T> сами, но это единственное решение, которое я знаю. Dictionary<Peptide, Peptide> или же Dictionary<string, Peptide> Решение, вероятно, не настолько неэффективно - если вы тратите только одну ссылку на запись, я думаю, это будет относительно незначительным.

На самом деле, если вы удалите hCode член от Peptide, это сохранит вам 4 байта на объект, который в любом случае равен размеру ссылки в x86... нет смысла кэшировать хэш, насколько я могу судить, поскольку вы будете вычислять хэш каждого объекта только один раз, по крайней мере, в коде, который вы показали.

Если вы действительно отчаянно нуждаетесь в памяти, я подозреваю, что вы могли бы сохранить последовательность значительно эффективнее, чем как string, Если вы дадите нам больше информации о том, что содержится в этой последовательности, мы можем внести некоторые предложения.

Я не знаю, что есть какая-то особенно веская причина, почему HashSet это не разрешает, за исключением того, что это относительно редкое требование - но это то, что я видел запрашиваемым и в Java...

Использовать Dictionary<string, Peptide>,

Другие вопросы по тегам