0

I have a dictionary where I'm trying to find the max of a specific class value, similar to getting max of a list. I've been searching for a couple of hours but all I'm finding is how to grab a value from a dictionary that has a key and a single value. I've also come across Linq but I'm not finding anything on how to search a dictionary's class values for the Max value. I'm pretty sure there is a way and I'm just missing something?

In my case, I'm trying to find the Max lineDistance of my class LineInfo

Links that I have found are close

this one but it only deals with a single key and a single value, not a class

this one seems like it might be on the right track but the checked answer suggests to run a nested foreach. I would imagine there's an easier / more sosphisticated way?

Any and all help is appreciated.

here is my code, it's fairly simple:

class LineInfo
    {
        public double lineDistance { get; set; }
        public LineSegment2d lineSegment2D1 { get; set; }
        public LineSegment2d lineSegment2D2 { get; set; }
    }

var lines = new Dictionary<int, LineInfo>();

double pointDistance0 = lineSegment2DList[i].StartPoint.GetDistanceTo(lineSegment2DList[j].StartPoint);
lines.Add(0, new LineInfo {lineDistance = pointDistance0, lineSegment2D1 = lineSegment2DList[i], lineSegment2D2 = lineSegment2DList[j] });

double pointDistance1 = lineSegment2DList[i].StartPoint.GetDistanceTo(lineSegment2DList[j].EndPoint);
lines.Add(1, new LineInfo { lineDistance = pointDistance1, lineSegment2D1 = lineSegment2DList[i], lineSegment2D2 = lineSegment2DList[j] });

double pointDistance2 = lineSegment2DList[i].EndPoint.GetDistanceTo(lineSegment2DList[j].StartPoint);
lines.Add(2, new LineInfo { lineDistance = pointDistance2, lineSegment2D1 = lineSegment2DList[i], lineSegment2D2 = lineSegment2DList[j] });


double pointDistance3 = lineSegment2DList[i].EndPoint.GetDistanceTo(lineSegment2DList[j].EndPoint);
lines.Add(3, new LineInfo { lineDistance = pointDistance3, lineSegment2D1 = lineSegment2DList[i], lineSegment2D2 = lineSegment2DList[j] });


Cflux
  • 1,423
  • 3
  • 19
  • 39

2 Answers2

5

To get LineInfo with maximum lineDistance you can use Values collection. Since there is no MaxBy in standard LINQ you can achieve similar effect with Aggregate:

var max = lines.Values
    .Aggregate((acc, curr) => acc.lineDistance > curr.lineDistance ? acc: curr);
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • How is this different from accepted [answer](https://stackoverflow.com/a/10290858/4728685) in question, mentioned by OP? – Pavel Anikhouski Aug 12 '20 at 22:48
  • @PavelAnikhouski, I didn't know how to access a specific field in my class, the `lineDistance` values. Guru's answer allows me to do that. – Cflux Aug 13 '20 at 17:31
2

If I'm understanding the question correctly, there's an overload for Max in Linq which allows you to specify a property, i.e:

double max = lines.Max(x => x.Value.lineDistance);

Edit

If you're wanting the object, than @itsme86 solution works the best:

LineInfo maxLineInfo = lines.Values.OrderByDescending(line => line.lineDistance).First();
Hayden
  • 2,902
  • 2
  • 15
  • 29
  • Yes, but this only returns the max `lineDistance` value, not the object with the max `lineDistance` value. Maybe that's what OP is after. It's kind of unclear. – itsme86 Aug 11 '20 at 23:09
  • @itsme86 Ah I didn't realise, I added your solution and credited you, as it's the simplest solution. – Hayden Aug 11 '20 at 23:13
  • 1
    The reason why @itsme86 did not post `OrderBy` comment as an answer because it is conceptually wrong way to find "Max by" - regular developers have hard time suggesting O(n log n) answer when O(n) is easily achievable - https://www.bing.com/search?q=c%23+max+by+propery - https://stackoverflow.com/questions/914109/how-to-use-linq-to-select-object-with-minimum-or-maximum-property-value – Alexei Levenkov Aug 11 '20 at 23:44