Question

Everybody! How can I get minimal value of an int array in specific range in C#? For example: int[] array= new int{1,2,3,4,5,6,7,8,76,45}; And I want to get a minimal value between 3-rd and 8-th element. Maybe it is possible to get via LINQ queries?

Was it helpful?

Solution

array.Skip(2).Take(5).Min();

OTHER TIPS

I figure I may as well add my tuppence to this. As Jason objects to the fact that we're saying how many we're skipping rather than the end index, we can add a simple extension method:

public static IEnumerable<T> WithIndexBetween<T>(this IEnumerable<T> source,
    int startInclusive, int endExclusive)
{
    // The two values can be the same, yielding no results... but they must
    // indicate a reasonable range
    if (endExclusive < startInclusive)
    {
        throw new ArgumentOutOfRangeException("endExclusive");
    }
    return source.Skip(startInclusive).Take(endExclusive - startInclusive);
}

Then:

int min = array.WithIndexBetween(2, 7).Min();

Adjust the extension method name to taste. (Naming is hard, and I'm not going to spend ages coming up with a nice one here :)

int min = array.Where((value, index) => index >= 2 && index <= 7).Min(); 

EDIT

Actually, the approach above is quite inefficient, because it enumerates the whole sequence, even though we're not interested in items with an index higher than 7. A better solution would be to use TakeWhile:

int min = array.TakeWhile((value, index) => index <= 7).Skip(2).Min();

Unfortunately it's not very readable... The best option to make it nicer is probably to create a custom extension method, as shown in Jon's answer.

int[] arr = {0,1,2,3,4,5,6,7,8};
int start = 3;
int end = 8;
int min = arr.Skip(start - 1).Take(end - start).Min();

Just to add another option:

int start = 3;
int end = 8;
var min = Enumerable.Range(start - 1,end - start).Select(idx => array[idx]).Min();

AFAIK, this is "theorically" faster if you have to take a range near to the end of the one, and your array is really really long.

That's because (again AFAIK) Skip() doesn't take into account that is an array (i.e. can be accessed randomly in O(1)) and enumerates it anyway.

array.Skip(3).Take(4).Min();

Personally, I'd prefer this:

public static class ArrayExtensions {
    public static bool ArrayAndIndexesAreValid(
        T[] array,
        int startInclusive,
        int endExclusive
    ) {
    return array != null &&
           array.Length > 0 &&
           startInclusive >= 0 && startInclusive < array.Length &&
           endExclusive >= 1 && endExclusive <= array.Length &&
           startInclusive < endExclusive;
    }
    public static IEnumerable<T> Slice<T>(
        this T[] array,
        int startInclusive,
        int endExclusive
    ) {
        Contract.Requires<ArgumentException>(ArrayAndIndexesAreValid(
            array,
            startInclusive,
            endExclusive)
        );
        for (int index = startInclusive; index < endExclusive; index++) {
            yield return array[index];
        }
    }
    public static T MinimumInIndexRange<T>(
        this T[] array,
        int startInclusive,
        int endExclusive
    ) where T : IComparable {
        Contract.Requires<ArgumentException>(ArrayAndIndexesAreValid(
            array,
            startInclusive,
            endExclusive)
        );
        return array.Slice(startInclusive, endExclusive).Min();
    }

    public static T MaximumInIndexRange<T>(
        this T[] array,
        int startInclusive,
        int endExclusive
    ) where T : IComparable {
        Contract.Requires<ArgumentException>(ArrayAndIndexesAreValid(
            array,
            startInclusive,
            endExclusive)
        );
        return array.Slice(startInclusive, endExclusive).Max();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top