我有一个场景,记忆保存是最重要的。我试图将超过1gb的肽序列读入内存,并将共享相同序列的肽实例组合在一起。我将肽对象存储在一个散列中,以便快速检查是否有重复,但发现您无法访问集合中的对象,即使在知道集合包含该对象之后。
内存非常重要,如果可能的话,我不想复制数据。(否则,我会将我的数据结构设计为:peptides=Dictionary<string, Peptide>,但这会在dictionary和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.Contains()返回true,那么您的对象是等价的。它们在值上可能是等价的,但是我需要引用相同的内容,因为我在肽类中存储了额外的信息。
我唯一想到的解决方案是Dictionary<Peptide, Peptide>其中键和值都指向同一个引用。但这看起来很俗气。是否有其他数据结构来完成此任务?

最佳答案

基本上你可以自己重新实现,但这是我知道的唯一解决方案。不过,HashSet<T>Dictionary<Peptide, Peptide>解决方案可能并没有那么低效——如果您只是在每个条目中浪费一个引用,我可以想象这将是相对无关紧要的。
事实上,如果您从Dictionary<string, Peptide>中删除hCode成员,则每个对象可以安全地保存4个字节,不管怎样,它的大小与x86中的引用相同…据我所知,缓存散列是没有意义的,因为您只需计算每个对象的散列一次,至少在您显示的代码中是这样。
如果你真的非常渴望记忆,我想你可以把序列存储得比Peptide高效得多。如果你给我们更多关于序列包含什么的信息,我们可以在那里提出一些建议。
我不知道为什么string不允许这样做,除了这是一个相对少见的需求之外,还有什么特别重要的原因-但我也看到Java中也有这样的需求……

09-25 18:52