简体   繁体   English

对象列表中的不同值

[英]Distinct values from List of objects

I need your help. 我需要你的帮助。 I am trying to get distinct values from List of objects. 我试图从对象列表中获得不同的值。 My class looks like this: 我的课看起来像这样:

class Chromosome
{
    public bool[][] body { get; set; }
    public double fitness { get; set; }
}

Now I have List<Chromosome> population . 现在我有了List<Chromosome> population And now what I need is a way, how I can get new list: List<Chromosome> newGeneration . 现在,我需要的是一种获取新列表的方法: List<Chromosome> newGeneration This new list will contain only unique chromosomes from original list - population. 这个新列表将仅包含原始列表中的唯一染色体-种群。

Chromosome is unique, when his whole body (which in this case is 2D bool array) is unique in comparison to the other chromosomes. 当他的整个身体 (在本例中为2D布尔数组) 与其他染色体相比是唯一的时,染色体就是唯一的。 I know, that there is something like MoreLINQ, but I am not sure, whether I should use 3rd party code and I know that I should overwrite some methods, but I am kind of lost. 我知道,有类似MoreLINQ的东西,但是我不确定是否应该使用第三方代码,我知道我应该覆盖一些方法,但是我有点迷失了。 So I would really appreciate some nice step by step description, that even idiot could accomplish :) THX 因此,我非常感谢您提供一些不错的逐步说明,即使是白痴也可以完成:) THX

First, implement the equality operator (this goes into class Chromosome ): 首先,实现相等运算符(这属于class Chromosome ):

public class Chromosome : IEquatable<Chromosome>
{

    public bool[][] body { get; set; }
    public double fitness { get; set; }

    bool IEquatable<Chromosome>.Equals(Chromosome other)
    {
        // Compare fitness
        if(fitness != other.fitness) return false;

        // Make sure we don't get IndexOutOfBounds on one of them
        if(body.Length != other.body.Length) return false;

        for(var x = 0; x < body.Length; x++)
        {
            // IndexOutOfBounds on inner arrays
            if(body[x].Length != other.body[x].Length) return false;

            for(var y = 0; y < body[x].Length; y++)
                // Compare bodies
                if(body[x][y] != other.body[x][y]) return false;
        }

        // No difference found
        return true;
    }

    // ReSharper's suggestion for equality members

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }
        if (ReferenceEquals(this, obj))
        {
            return true;
        }
        if (obj.GetType() != this.GetType())
        {
            return false;
        }
        return this.Equals((Chromosome)obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return ((this.body != null ? this.body.GetHashCode() : 0) * 397) ^ this.fitness.GetHashCode();
        }
    }
}

Then, use Distinct : 然后,使用Distinct

var newGeneration = population.Distinct().ToList();
public class ChromosomeBodyComparer : IEqualityComparer<Chromosome>
{
  private bool EqualValues(bool[][] left, bool[][] right)
  {
    if (left.Length != right.Length)
    {
      return false;
    }
    return left.Zip(right, (x, y) => x.SequenceEquals(y)).All();
  }

  public bool Equals(Chromosome left, Chromosome right)
  {
    return EqualValues(left.body, right.body)
  }

     //implementing GetHashCode is hard.
     // here is a rubbish implementation.
  public int GetHashCode(Chromosome c)
  {
    int numberOfBools = c.body.SelectMany(x => x).Count();
    int numberOfTrues = c.body.SelectMany(x => x).Where(b => b).Count();
    return (17 * numberOfBools) + (23 * numberOfTrues);

  }
}

Called by: 致电者:

List<Chromosome> nextGeneration = population
  .Distinct(new ChromosomeBodyComparer())
  .ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM