Lithiumme
Lithiumme

Reputation: 41

Compare two dictionaries and determine the minimum value using Linq

I'm trying to figure out a way to use Linq to compare two dictionaries against each other and determine the minimum value in DictB for the keys from DictA.

DictA: { 1, "Ron" }, { 3, "Alice" }
DictB: { 1, 9 }, { 2, 7 }, { 3, 10 }, { 4, 8 }, { 5, 12 }

Assuming that the keys on both dictionaries are the unique ids that represent both the users and their scores I want to be able to determine the user who got the lowest score between the users in DictA, which would be user 1 ("Ron") with a score of 9.

I'm assuming it would have to be something along the lines of:

var pLoser = DictA[
    DictB
        .Where(x => DictA.ContainsKey(x.Key))
        .Aggregate((l, r) => l.Value < r.Value ? l : r)
        .Key
    ];

I was wondering if this is the correct way of achieving what I want or if there's a better way to do it.

Upvotes: 0

Views: 173

Answers (3)

Igor
Igor

Reputation: 62213

One way to do it is using a Join, then project the result to an anonymous type with some common sense property names, then sort by the score and take the first returned value. This assumes there will always be a returned value but if that is not always the case you could also use FirstOrDefault instead of First.

var lowestScore = DictA.Join(DictB, entryA => entryA.Key, entryB => entryB.Key, (entryA, entryB) => new {Id = entryA.Key, Name = entryA.Value, Score = entryB.Value})
    .OrderBy(x => x.Score)
    .First();

Do note that if there are competing scores for last place and you want to return all of them then using a GroupBy would make more sense.

Upvotes: 0

D Stanley
D Stanley

Reputation: 152521

Seems like a join is a natural solution here:

var lowestScore = 
    (from a in dictA
    join b in dictB on a.Key equals b.Key
    orderby b.Value
    select new {Name = a.Value, Score = b.Value}).First()

Upvotes: 0

Hogan
Hogan

Reputation: 70523

I think I would do it like this -- there may be faster but it seems best -- order by value check if it exists and take the first one:

var pLoser = DictA[
  DictB
    .OrderBy(x => x.Value) // lowest values first
    .Where(x => DictA.ContainsKey(x.Key))
    .FirstOrDefault()
    .Key
];

This should leverage the lazy nature of linq to do the least amount of work to solve the problem.

Upvotes: 1

Related Questions