Frix
Frix

Reputation: 101

Improve comparing between two collections - LINQ? C#

Edit: _existingRatings and _targetRatings are both collections from a database, where Rating and RatingType are both key/values.

I've got two RatingDto collections that I need to compare each other against: _existingRates and _targetRates. I'll be simply doing a comparison on the RatingTypeId, then need to check if the same one in the _targetRates has an empty Rating string.

As it's Monday morning, my brain is still asleep and I'm sure there's a better and simpler way to do this with LINQ. This is what I'm currently doing:

class RatingDto
{
        public int RatingTypeId { get; set; }
        public string RatingType { get; set; }
        public string Rating { get; set; }
}

foreach (var existing in _existingRatings)
{
    foreach(var target in _targetRatings)
    {
        if(existing.RatingTypeId == target.RatingTypeId)
        {
            if(target.Rating == string.Empty)
            {
                _targetHasMissingRatings = true;
            }
        }
    }
}

This should be okay as the maximum amount is around 7 in each collection, but I'm sure there's a better and cleaner way with LINQ.

Upvotes: 2

Views: 103

Answers (2)

jdweng
jdweng

Reputation: 34421

Use IComparable so you can use OrderBy on the entire class or simply compare two instances of the class.

List<RatingDto> ordered = _existingRatings.OrderBy(x => x).ToList();

See code below :

    class RatingDto : IComparable<RatingDto>
    {
        public int RatingTypeId { get; set; }
        public string RatingType { get; set; }
        public string Rating { get; set; }

        public int CompareTo(RatingDto  other)
        {
            if (this.RatingTypeId != other.RatingTypeId)
            {
                return this.RatingTypeId.CompareTo(other.RatingTypeId);
            }
            else
            {
                return this.RatingType.CompareTo(other.RatingType);
            }
        }
    }

Code would look like this :

            List<RatingDto> _existingRatings = new List<RatingDto>(); 
            List<RatingDto> _targetRatings = new List<RatingDto>();
            Boolean _targetHasMissingRatings = false;

            foreach (var existing in _existingRatings)
            {
                foreach (var target in _targetRatings)
                {
                    if (existing == target)
                    {
                         _targetHasMissingRatings = true;
                         break;
                    }
                }
                if (_targetHasMissingRatings == true) break;
            }

Upvotes: 1

CorrM
CorrM

Reputation: 527

That's should what you are looking for : (i love to use string.IsNullOrEmpty rather than cmp string.Empty)

_targetHasMissingRatings = _existingRatings.Any(er => string.IsNullOrEmpty(_targetRatings.FirstOrDefault(tr => er.RatingTypeId == tr.RatingTypeId)?.Rating));

Upvotes: 1

Related Questions