大家好! 在C#中,如何获取int数组特定范围内的最小值? 例如: int[] array= new int{1,2,3,4,5,6,7,8,76,45}; 我想要获取第3个到第8个元素之间的最小值。 也许可以通过LINQ查询来实现?
array.Skip(2).Take(5).Min();
value
和index
参数。如果您想使它更与“开始”和“结束”相关,则Eric的方法是一个不错的选择。 - Jon Skeetvalue
变量引用的值只是一个整数。如果你要过载“值”这个词来表示“序列中的条目”和“序列中条目的值”,那么在我看来,你需要更大的努力来说服我们你在争论简单性 :) (顺便评论一下我的答案吗?) - Jon Skeet我想我可以为此添加我的意见。由于Jason反对我们说跳过多少而不是结束索引,我们可以添加一个简单的扩展方法:
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();
根据个人喜好调整扩展方法名称。(命名很难,我不会花费太长时间在这里想出一个好的名称 :)
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();
int min = array.Where((value, index) => index >= 2 && index <= 7).Min();
编辑
实际上,以上方法相当低效,因为它枚举了整个序列,即使我们对索引大于7的项目不感兴趣。更好的解决方案是使用TakeWhile
:
int min = array.TakeWhile((value, index) => index <= 7).Skip(2).Min();
很遗憾,这段文字不太易读... 使其更好的选项可能是创建一个自定义扩展方法,就像Jon的答案中所示。
还有一个选项:
int start = 3;
int end = 8;
var min = Enumerable.Range(start - 1,end - start).Select(idx => array[idx]).Min();
Skip()
没有考虑到它是一个数组(即可以在O(1)的时间内随机访问),仍然枚举它。IList<T>
)的特定情况下,它更快 - 但当然在一般序列情况下会崩溃。当然,“Skip”在未来的版本中可能也会被修复 :) - Jon Skeet就我个人而言,我更喜欢这样:
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();
}
}
int.MaxValue
,这可能不是一个好主意。它还混合了“查找最小值”和“考虑数组切片”的逻辑,而基于LINQ的解决方案则没有这样做。如果您需要找到数组切片的最大值,则需要重复所有切片逻辑。 - Jon Skeetlong[]
等中获取最小值时重新实现它。在我看来,将此操作泛化是易如反掌的。当然,在返回空数组切片的值时这样做很困难... - Jon Skeetlong[]
中的最小值,也不需要重新实现计算最大值的分割等操作。由于空序列没有最小值(序列中最小值的定义是值v
在序列中 ,使得对于序列中所有其他值w
,都有v<=w
;这里,“<=”是一个通用的全序关系),我们应该在这种情况下引发异常。如果愿意的话,可以包含带有默认值的重载,以在空数组的情况下用作最小/最大值。 - jasonarray.Skip(3).Take(4).Min();