hoping someone can help me out with something. I have an object which contains a list of values and an identifier similar to this:
public class MyObj
{
public string Id { get; set; }
public List<MyOtherObj> OtherObject { get; set; }
public class MyOtherObj
{
public int Score { get; set; }
}
}
I then have a method similar like this:
public MyObj GetHighestScoreThatIsNotDuplicated(IEnumerable<MyObj> myObjs)
{
//Not sure what to do here
return new MyObj();
}
So now if you imagine the input being along these lines:
MyObj1: Id = 1, OtherObj (list of score) = 5,4,3,2,1
MyObj2: Id = 2, OtherObj (list of score) = 10,5,4,3,2
From here the MyObj2 should be returned as 10 is the highest score and it is not present within the other list.
However if the input was:
MyObj1: Id = 1, OtherObj (list of score) = 5,4,3,1
MyObj2: Id = 2, OtherObj (list of score) = 5,4,3,2,1
MyObj3: Id = 3, OtherObj (list of score) = 5,4,3,1
Then the output would be MyObj2 as 5, 4 & 3 are in all the lists however 2
I'm imagining this will be some kind of recursive method which is fine but I just can't think how to do this in any kind of a clean way.
CodePudding user response:
How efficient does it have to be? A trivial solution might involve the following steps:
- Count each score value
- Only select scores with count==1
- Select highest score
- Find object which contains this score
Something like:
var groupedScores = myObjs
.SelectMany(o => o.OtherObject)
.Select(o => o.Score)
.GroupBy(x => x);
var highestScore = groupedScores
.Where(g => g.Count() == 1)
.SelectMany(x => x)
.Max();
var result = myObjs
.FirstOrDefault(o => o.OtherObject.Any(oo => oo.Score == highestScore));
An alternative would be turning your structure inside-out, using an anonymous type to map each score to the top-level object, but the idea is still the same:
var result = myObjs
.SelectMany(o => o.OtherObject.Select(oo => new {
Obj = o,
Score = oo.Score
}))
.GroupBy(x => x.Score)
.Where(g => g.Count() == 1)
.SelectMany(g => g)
.MaxBy(g => g.Score)
.Obj;