Question

I need to compare two lists of objects. This objects have again a list of other object. I need to do it with a join.

public class MaterialXML
{
    public string Reference {get;set;}
    public string MeasurementUnitCode {get;set;}
    public IEnumerable<AlternateUnitXML> AlternateUnits { get; set; }
}

public class AlternateUnitXML
{
    public string Code { get; set; }
    public decimal PrimaryQuantity{get;set;}
    public decimal SecondaryQuantity{get; set;}

}

With this Class I normally compare on this way: I go to explain it without the IEnumerable on the MaterialXML object.

IEnumerable<MaterialXML> matListA=repository.getMatA();
IEnumerable<MaterialXML> matListB=repository.getMatB();

//For get the objects in a that are similar in b:

IEnumerable<MaterialXML> matOnASimilarToB= from p in matListA
                                           join h in matListB on 
                                           new{ p.Reference , 
                                                p.MeasurementUnitCode
                                              }
                                           equals
                                           new{ h.Reference , 
                                                h.MeasurementUnitCode
                                              }
                                           select p;

My problem is if I try to compare the materialsxml with the same reference, measurementunitcode, and the same list of AlternateUnitCode.

It is possible?

For example:

  1. List A:

    1. Reference = MatA1 MeasurerementUnitCode = T AlternateUnits:
        1. Code: A PrimaryQuantity: 1 SecundaryQuantity: 2
        1. Code: B PrimaryQuantity: 1 SecundaryQuantity: 3
        1. Code: C PrimaryQuantity: 1 SecundaryQuantity: 4
    2. Reference = MatA2 MeasurerementUnitCode = T AlternateUnits:
        1. Code: A PrimaryQuantity: 1 SecundaryQuantity: 12
        1. Code: B PrimaryQuantity: 1 SecundaryQuantity: 13
        1. Code: C PrimaryQuantity: 1 SecundaryQuantity: 14
    3. Reference = MatA3 MeasurerementUnitCode = T AlternateUnits:
        1. Code: A PrimaryQuantity: 1 SecundaryQuantity: 12
        1. Code: B PrimaryQuantity: 1 SecundaryQuantity: 13
        1. Code: C PrimaryQuantity: 1 SecundaryQuantity: 14
        1. Code: D PrimaryQuantity: 1 SecundaryQuantity: 15
  2. List B:

    1. Reference = MatA1 MeasurerementUnitCode = T AlternateUnits:
        1. Code: A PrimaryQuantity: 1 SecundaryQuantity: 2
        1. Code: B PrimaryQuantity: 1 SecundaryQuantity: 3
        1. Code: C PrimaryQuantity: 1 SecundaryQuantity: 4
    2. Reference = MatA2 MeasurerementUnitCode = T AlternateUnits:
        1. Code: A PrimaryQuantity: 1 SecundaryQuantity: 12
        1. Code: B PrimaryQuantity: 1 SecundaryQuantity: 13
        1. Code: C PrimaryQuantity: 1 SecundaryQuantity: 74
    3. Reference = MatA3 MeasurerementUnitCode = T AlternateUnits:
        1. Code: A PrimaryQuantity: 1 SecundaryQuantity: 12
        1. Code: B PrimaryQuantity: 1 SecundaryQuantity: 13
        1. Code: C PrimaryQuantity: 1 SecundaryQuantity: 14

In the example that data in the array a y b, only de MatA1 are identical. The matA2 is diferent because the Alternate Unit C have in one case 14 and in the second case 78. The matA3 is diferent because in one case has 3 alternate units and in the other case has 4.

Was it helpful?

Solution

You'd need to start with some custom comparers to customize the way that the join performs matching:

    public class MaterialXMLComparer : IEqualityComparer<MaterialXML>
    {
        private  IEqualityComparer<AlternateUnitXML> _alternateComparer;
        public MaterialXMLComparer(IEqualityComparer<AlternateUnitXML> alternateComparer)
        {
            _alternateComparer = alternateComparer;
        }
        public bool Equals(MaterialXML x, MaterialXML y)
        {
            bool firstLevelEqual = (x.Reference == y.Reference) &&
                (x.MeasurementUnitCode == y.MeasurementUnitCode);

            if (firstLevelEqual)
            {
                if (x.AlternateUnits.SequenceEqual(y.AlternateUnits, _alternateComparer))
                {
                    return true;
                }
            }

            return false;
        }
        public int GetHashCode(MaterialXML obj)
        {
            return obj.Reference.GetHashCode();
        }
    }
    public class AlternateUnitXMLComparer : IEqualityComparer<AlternateUnitXML>
    {

        public bool Equals(AlternateUnitXML x, AlternateUnitXML y)
        {
            return (x.Code == y.Code) &&
                (x.PrimaryQuantity == y.PrimaryQuantity) &&
                (x.SecondaryQuantity == y.SecondaryQuantity);
        }

        public int GetHashCode(AlternateUnitXML obj)
        {
            return obj.Code.GetHashCode();
        }
    }

Then, you can use the Join method directly to add in the custom comparers:

        var joinedList = matListA.Join(matListB,
            x => x,
            y => y,
            (x, y) => x,
            new MaterialXMLComparer(new AlternateUnitXMLComparer()));

joinedList now contains just the entry from matListA that matched some entry from matListB.

OTHER TIPS

Is perfect.

I use that code and the objects are correctly compared.

Really, i have one more fields in the entity

public class MaterialXMLComparer : IEqualityComparer<MaterialXML>
    {
        private IEqualityComparer<AlternateUnitXML> _alternateComparer;
        private IEqualityComparer<MaterialsPatnerXMLforMaterial> _matPartnerComparer;

        public MaterialXMLComparer(IEqualityComparer<AlternateUnitXML> alternateComparer,IEqualityComparer<MaterialsPatnerXMLforMaterial> matPartnerComparer)
        {
            _alternateComparer = alternateComparer;
            _matPartnerComparer = matPartnerComparer;
        }
        public bool Equals(MaterialXML x, MaterialXML y)
        {
            bool firstLevelEqual = (x.Reference == y.Reference) &&
                    (x.MeasurementUnitCode == y.MeasurementUnitCode) &&
                    (x.Denomination == y.Denomination) &&
                    (x.Weight == y.Weight) &&
                    (x.PieceType == y.PieceType) &&
                    (x.Type == y.Type) &&
                    (x.Position == y.Position);

            bool secondLevelEqual=false;
            if (firstLevelEqual)
            {
                if (x.AlternateUnits.SequenceEqual(y.AlternateUnits, _alternateComparer))
                {
                    secondLevelEqual= true;
                }
            }

            if (secondLevelEqual)
            {
                if (x.MaterialsPartner.SequenceEqual(y.MaterialsPartner, _matPartnerComparer))
                {
                    return true;
                }
            }

            return false;
        }
        public int GetHashCode(MaterialXML obj)
        {
            return obj.Reference.GetHashCode();
        }
    }

Thanks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top