C# 确定一个数字是否在一组指定的范围内

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1137499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 09:06:34  来源:igfitidea点击:

Determine if a number falls within a specified set of ranges

c#range

提问by Steve Dignan

I'm looking for a fluent way of determining if a number falls within a specified set of ranges. My current code looks something like this:

我正在寻找一种流畅的方法来确定一个数字是否在一组指定的范围内。我当前的代码如下所示:

int x = 500; // Could be any number

if ( ( x > 4199 && x < 6800 ) ||
     ( x > 6999 && x < 8200 ) ||
     ( x > 9999 && x < 10100 ) ||
     ( x > 10999 && x < 11100 ) ||
     ( x > 11999 && x < 12100 ) )
{
    // More awesome code
}

Is there a better way of doing this?

有没有更好的方法来做到这一点?

采纳答案by Anton Gogolev

Extension methods?

扩展方法?

bool Between(this int value, int left, int right)
{ 
   return value > left && value < right; 
}

if(x.Between(4199, 6800) || x.Between(6999, 8200) || ...)

You can also do this awful hack:

你也可以做这个可怕的黑客:

bool Between(this int value, params int[] values)
{
    // Should be even number of items
    Debug.Assert(values.Length % 2 == 0); 

    for(int i = 0; i < values.Length; i += 2)
        if(!value.Between(values[i], values[i + 1])
            return false;

    return true;
}

if(x.Between(4199, 6800, 6999, 8200, ...)

Awful hack, improved:

可怕的黑客,改进:

class Range
{
    int Left { get; set; }
    int Right { get; set; }

    // Constructors, etc.
}

Range R(int left, int right)
{
    return new Range(left, right)
}

bool Between(this int value, params Range[] ranges)
{
    for(int i = 0; i < ranges.Length; ++i)
        if(value > ranges[i].Left && value < ranges[i].Right)
            return true;

    return false;
}

if(x.Between(R(4199, 6800), R(6999, 8200), ...))

Or, better yet (this does not allow duplicate lower bounds):

或者,更好(这不允许重复的下限):

bool Between(this int value, Dictionary<int, int> ranges)
{
    // Basically iterate over Key-Value pairs and check if value falls within that range
}

if(x.Between({ { 4199, 6800 }, { 6999, 8200 }, ... }

回答by Jon Skeet

Define a Range type, then create a set of ranges and an extension method to see whether a value lies in any of the ranges. Then instead of hard-coding the values, you can create a collection of ranges and perhaps some individual ranges, giving them useful names to explain whyyou're interested in them:

定义一个 Range 类型,然后创建一组范围和一个扩展方法来查看某个值是否位于任何范围内。然后,而不是硬编码值,你可以创建范围,也许个别范围的集合,给他们有用的名称解释为什么你对他们感兴趣:

static readonly Range InvalidUser = new Range(100, 200);
static readonly Range MilkTooHot = new Range (300, 400);

static readonly IEnumerable<Range> Errors =
    new List<Range> { InvalidUser, MilkTooHot };

...

// Normal LINQ (where Range defines a Contains method)
if (Errors.Any(range => range.Contains(statusCode))
// or (extension method on int)
if (statusCode.InAny(Errors))
// or (extension methods on IEnumerable<Range>)
if (Errors.Any(statusCode))

You may be interested in the generic Rangetype which is part of MiscUtil. It allows for iteration in a simple way as well:

您可能对Range属于MiscUtil一部分的泛型类型感兴趣。它也允许以一种简单的方式进行迭代:

foreach (DateTime date in 19.June(1976).To(25.December(2005)).Step(1.Days()))
{
    // etc
}

(Obviously that's also using some DateTime/TimeSpan-related extension methods, but you get the idea.)

(显然这也使用了一些与 DateTime/TimeSpan 相关的扩展方法,但你明白了。)

回答by KM.

if you need to iterate over the value pairs at some point, I suggest you capture the maximum lower value and the minimum upper value as you do into variables and do:

如果您需要在某个时候迭代值对,我建议您像在变量中一样捕获最大下限值和最小上限值,然后执行以下操作:

if ( x>max_lower && x <min_upper)
{
    // More awesome code

}

回答by LBushkin

Try something like:

尝试类似:

struct Range
{
   public readonly int LowerBound;
   public readonly int UpperBound; 

   public Range( int lower, int upper )
   { LowerBound = lower; UpperBound = upper; }

   public bool IsBetween( int value )
   { return value >= LowerBound && value <= UpperBound; }
}

public void YourMethod( int someValue )
{
   List<Range> ranges = {new Range(4199,6800),new Range(6999,8200),
                         new Range(9999,10100),new Range(10999,11100),
                         new Range(11999,12100)};

   if( ranges.Any( x => x.IsBetween( someValue ) )
   {
      // your awesome code...
   }
}

回答by Bob

class Range { 

    public Range(int x, int y) {
        X = x;
        Y = y;
    }

    public int X { get; set; }
    public int Y { get; set; }
}

var ranges = new List<Range>();
ranges.Add(new Range(4199,6800));
ranges.Add(new Range(6999,8200));
ranges.Add(new Range(9999,10100));
ranges.Add(new Range(10999,11100));
ranges.Add(new Range(11999,12100));

bool inRange = ranges.Count(r => x >= r.X && x <= r.Y) > 0;
//or -- Based on Jons recommendation
bool inRange = ranges.Any(r => x >= r.X && x <= r.Y);

回答by Scott Ivey

I personally prefer the extension method suggested by @Anton - but if you can't do that, and are going to stick with your current code, I think you could make it more readable by reversing the first set of conditions on each line as follows...

我个人更喜欢@Anton 建议的扩展方法 - 但如果你不能这样做,并且要坚持你当前的代码,我认为你可以通过反转每一行的第一组条件来使其更具可读性,如下所示...

int x = 500; // Could be any number
if ( ( 4199 < x && x < 6800 ) ||
     ( 6999 < x && x < 8200 ) ||
     ( 9999 < x && x < 10100 ) ||
     ( 10999 < x && x < 11100 ) ||
     ( 11999 < x && x < 12100 ) )
{
    // More awesome code
}

回答by Rob Cowell

LINQ approach :

LINQ 方法:

Add the reference:

添加参考:

using System.Linq;

        /// <summary>
        /// Test to see if value is in specified range.
        /// </summary>
        /// <param name="aStart">int</param>
        /// <param name="aEnd">int</param>
        /// <param name="aValueToTest">int</param>
        /// <returns>bool</returns>
        public static bool CheckValueInRange(int aStart, int aEnd, int aValueToTest)
        {
            // check value in range...
            bool ValueInRange = Enumerable.Range(aStart, aEnd).Contains(aValueToTest);
            // return value...
            return ValueInRange;
        }

回答by Why...because.its.free

In Pascal (Delphi) you have the following statement:

在 Pascal (Delphi) 中,您有以下语句:

if x in [40..80] then
begin
end

So if a value x falls in that range you execute your command. I was looking for the C# equivalent to this but can't find something as simple and 'elegant' as this.

因此,如果值 x 落在该范围内,则执行命令。我一直在寻找与此等效的 C#,但找不到像这样简单和“优雅”的东西。

This if in() then statement accepts strings, bytes, etc.

这个 if in() then 语句接受字符串、字节等。