Как получить доступ к ссылочным значениям 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...