C # массивов минимальное значение в определенном диапазоне - PullRequest
4 голосов
/ 10 декабря 2010

Всем!Как я могу получить минимальное значение массива int в определенном диапазоне в C #?Например: int [] array = new int {1,2,3,4,5,6,7,8,76,45};И я хочу получить минимальное значение между 3-м и 8-м элементом.Может быть, можно получить через запросы LINQ?

Ответы [ 7 ]

13 голосов
/ 10 декабря 2010
array.Skip(2).Take(5).Min();
6 голосов
/ 10 декабря 2010

Полагаю, я тоже могу добавить к этому свое терпение. Поскольку Джейсон возражает против того, что мы говорим, сколько мы пропускаем, а не конечный индекс, мы можем добавить простой метод расширения:

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);
}

Тогда:

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

Настройте имя метода расширения по вкусу. (Назвать сложно, и я не собираюсь целую вечность придумывать хороший здесь:)

3 голосов
/ 10 декабря 2010
int min = array.Where((value, index) => index >= 2 && index <= 7).Min(); 

РЕДАКТИРОВАТЬ

На самом деле, вышеприведенный подход довольно неэффективен, поскольку он перечисляет всю последовательность, даже если мы не заинтересованы в элементах с индексом выше 7. Лучшерешение было бы использовать TakeWhile:

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

К сожалению, это не очень читабельно ... Лучший способ сделать его лучше - это, вероятно, создать собственный метод расширения, как показано в ответе Джона.

2 голосов
/ 10 декабря 2010

Просто чтобы добавить еще один вариант:

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

AFAIK, это "теоретически" быстрее, если вам нужно взять диапазон ближе к концу, а ваш массив действительно очень длинный.

Это потому, что (снова AFAIK) Skip() не принимает во внимание, что это массив (то есть можно получить произвольный доступ в O (1)) и перечисляет его в любом случае.

2 голосов
/ 10 декабря 2010
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();
0 голосов
/ 10 декабря 2010

Лично я бы предпочел это:

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();
    }
}
0 голосов
/ 10 декабря 2010
array.Skip(3).Take(4).Min();
...