Take a look at this code:
ColorResult contains Index, Color Name, and Probability
Colors.Add(new ColorResult(1, "Unknown", 5f));
Colors.Add(new ColorResult(2, "Blue", 80f));
Colors.Add(new ColorResult(3, "Blue", 80f));
Colors.Add(new ColorResult(4, "Green", 40f));
Colors.Add(new ColorResult(5, "Blue", 80f));
Colors.Add(new ColorResult(6, "Blue", 80f));
Colors.Add(new ColorResult(7, "Red", 20f));
Colors.Add(new ColorResult(8, "Blue", 80f));
Colors.Add(new ColorResult(9, "Green", 5f));
Using LINQ, how would you accomplish the following:
1) Working sequentially, replace all items at the start of the List<> that have a Probability lower than 60 when the first TWO items that follow with a probability higher than 60 have the same value (“Unknown” becomes “Blue” because #2 and #3 are Blue and have Probability of 60+)
2) Replace any item with a probability lower than 60 that’s surrounded with FOUR neighbors have the same value (“Green” becomes “Blue” because #2, #3, #5 and #6 are Blue and have Probability of 60+)
3) Working sequentially, replace any items at the end of the List<> that are preceded by TWO items with the same value (same as the first part, but in reverse). In the sample data, nothing would happen to #9 since #7 would need to be “Blue” and would need 60+ Probability.
This is pretty easy with loops, but I am absolutely stumped on how to compare sequential “neighbors” in LINQ.
This was my original solution for part 1:
bool partOneCompleted = false;
for (int i = 0; i < Colors.Count; i++)
{
if (Colors[i].ResultConfidence > 60)
{
// This item does not need to be changed
partOneCompleted = true;
}
if (!partOneCompleted)
{
int twoItemsAway = i + 2;
if (twoItemsAway < Colors.Count)
{
if (Colors[twoItemsAway].Name == Colors[twoItemsAway - 1].Name && Colors[twoItemsAway].ResultConfidence > 60 && Colors[twoItemsAway - 1].ResultConfidence > 60)
{
// The next item, and the one after that both have the same value and 60+ confidence
for (int loopBack = i; loopBack >= 0; loopBack--)
{
Colors[loopBack].Name = Colors[twoItemsAway].Name;
}
partOneCompleted = true;
}
}
}
}
Can any LINQ experts please share the most efficient implementation?
I started with a test for part 1:
and implementation
then added a test for part 3, since it is a variation of part 1:
and implementation:
then, I tackled part 2. Again I started with a test:
and this implementation:
This time it seemed cleaner to pull out a helper class:
Finally, I created a consolidated test with your data:
and an implementation that uses the methods created above:
Were this my code base I would go on to add tests around edge cases like: all items having probability < 60 for parts 1 and 3; all but last … for part 1; all but first for part 3; etc.