Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I select the minimum sub-sequence using LINQ?

Tags:

linq

If I have an array of golf results:

 -3, +5, -3, 0, +1, +8, 0, +6, +2, -8, +5

I need to find a sequence of three adjacent numbers which have the minimum sum. For this example, the sub-sequences would be:

 [-3, +5, -3]
 [+5, -3,  0]
 [-3,  0, +1]
 ... etc ...
 [+2, -8, +5]

And the minimum sequence would be [-3, 0, +1] having a sum of -2.

like image 640
user3515324 Avatar asked Apr 09 '14 13:04

user3515324


People also ask

How to find minimum value in LINQ?

In LINQ, you can find the minimum element of the given sequence by using Min() function. This method provides the minimum element of the given set of values. It does not support query syntax in C#, but it supports in VB.NET. It is available in both Enumerable and Queryable classes in C#.

What does select in Linq return?

The Select() method invokes the provided selector delegate on each element of the source IEnumerable<T> sequence, and returns a new result IEnumerable<U> sequence containing the output of each invocation.

Why from comes before select in Linq?

The reason is, LINQ is used with C# or other programming languages, which requires all the variables to be declared first. From clause of LINQ query just defines the range or conditions to select records. So that's why from clause must appear before Select in LINQ.


3 Answers

You could use this LINQ query:

int[] golfResult = { -3, +5, -3, 0, +1, +8, 0, +6, +2, -8, +5 };
var combinations = from i in Enumerable.Range(0, golfResult.Length - 2)
                   select new { 
                       i1 = golfResult[i], 
                       i2 = golfResult[i + 1], 
                       i3 = golfResult[i + 2], 
                   };
var min = combinations.OrderBy(x => x.i1 + x.i2 + x.i3).First();
int[] minGolfResult = { min.i1, min.i2, min.i3 }; // -3, 0, +1

Of course you need to check if there are at least three results in the array.

like image 114
Tim Schmelter Avatar answered Jan 01 '23 19:01

Tim Schmelter


I'm not sure why you would do this with LINQ. I think a straight up iterative solution is easier to understand:

int[] scores = new[] { -3, 5, -3, 0, 1, 8, 0, 6, 2, -8, 5 };

int minimumSubsequence = int.MaxValue;
int minimumSubsequenceIndex = -1;

for (int i = 0; i < scores.Length - 2; i++)
{
    int sum = scores[i] + scores[i + 1] + scores[i + 2];

    if (sum < minimumSubsequence)
    {
        minimumSubsequence = sum;
        minimumSubsequenceIndex = i;
    }
}

// minimumSubsequenceIndex is index of the first item in the minimum subsequence
// minimumSubsequence is the minimum subsequence's sum.
like image 37
Andrew Whitaker Avatar answered Jan 01 '23 19:01

Andrew Whitaker


If you really want to do it in LINQ, you can go this way:

int length = 3;
var scores = new List<int>() { -3, +5, -3, 0, +1, +8, 0, +6, +2, -8, +5 };
var results =
    scores
    .Select((value, index) => new
    {
        Value = scores.Skip(index - length + 1).Take(length).Sum(),
        Index = index - length + 1
    })
    .Skip(length - 1)
    .OrderBy(x => x.Value)
    .First()
    .Index;

This creates a second list that sums all length preceeding elements and then sorts it. You have

like image 25
Konrad Kokosa Avatar answered Jan 01 '23 18:01

Konrad Kokosa