【问题标题】:How get range of numbers [duplicate]如何获得数字范围[重复]
【发布时间】:2011-09-16 04:45:38
【问题描述】:

我有一个数字 [1, 20] 的区间。

如果我决定禁止范围 [15, 18],我想要一个返回可用数字范围的方法。我的方法应该返回一个包含 [1,15] 和 [18, 20] 的列表

Range 对象可能看起来像这样

public class Range
{
     int Start {get;set;}
     int End {get;set;}
}

任何帮助将不胜感激。

【问题讨论】:

    标签: c#


    【解决方案1】:

    这个怎么样?

    IEnumerable<int> range = Enumerable.Range(1, 20);
    IEnumerable<int> banned = Enumerable.Range(15, 4);
    return range.Except(banned);
    

    Enumerable 类已经有一个静态方法,它将为您返回一系列值 - 使用这些语义可能更简单。

    【讨论】:

    • 这是我一直在寻找的答案。谢谢!
    • +1 用于小而干净的代码 :) 比其他答案好得多恕我直言
    • 这里讨论了这种方法的问题(尤其是性能):stackoverflow.com/a/5343052/2756574
    【解决方案2】:

    这是其中一种方式:

    static void Main(string[] args)
        {
            int[] allNumbers = Enumerable.Range(1, 20).ToArray();
            GetNumbers(ref allNumbers, new int[] { 16, 17 });
        }
    
        private static void GetNumbers(ref int[] nums, int[]exclude)
        {
            List<int> numsToExlucde =new List<int>();
            numsToExlucde.InsertRange(0, exclude);
            nums = nums.Where(w => !numsToExlucde.Contains(w)).ToArray();
        }
    

    【讨论】:

    • 这应该是公认的答案! Enumerable.Range 可能是获取数字范围的最简单方法。
    【解决方案3】:

    您有四种可能的情况。该方法可能如下所示(我假设范围仅包含整数):

    public class Range
    {
        public int Start { get; set; }
        public int End { get; set; }
    
        public IList<Range> Exclude(Range r)
        {
            if (r.Start <= Start && r.End < End)
            {
                return new List<Range>{new Range { Start = r.End + 1, End = End }};
            }
            else if (r.Start > Start && r.End >= End)
            {
                return new List<Range>{new Range { Start = Start, End = r.Start - 1 }};
            }
            else if (r.Start > Start && r.End < End)
            {
                return new List<Range>
                           {
                               new Range { Start = Start, End = r.Start - 1 },
                               new Range { Start = r.End + 1, End = End }
                           };
            }
            return new List<Range>();
        }
    }
    
    // ...
    
    static void Main(string[] args)
    {
        Range r = new Range { Start = 1, End = 20};
        var list = r.Exclude(new Range{ Start = 1, End = 2} );
    }
    

    【讨论】:

      【解决方案4】:

      这可以帮助您从另一个范围或一组范围中删除一个范围:

      public class Range {
      
        public int Start { get; private set; }
        public int End { get; private set; }
      
        public Range(int start, int end) {
          Start = start;
          End = end;
        }
      
        public IEnumerable<Range> RemoveFrom(Range range) {
          return RemoveFrom(new Range[] { range });
        }
      
        public IEnumerable<Range> RemoveFrom(IEnumerable<Range> items) {
          foreach (Range item in items) {
            if (End >= item.Start && Start <= item.End) {
              if (item.Start <= Start) {
                yield return new Range(item.Start, Start);
              }
              if (item.End >= End) {
                yield return new Range(End, item.End);
              }
            } else {
              yield return item;
            }
          }
        }
      
      }
      

      例子:

      Range range = new Range(1, 20);
      foreach (Range r in new Range(15,18).RemoveFrom(range)) {
        Console.WriteLine("{0} - {1}", r.Start, r.End);
      }
      

      输出:

      1 - 15
      18 - 20
      

      从其他范围中删除多个范围的示例:

      Range[] items = new Range[] { new Range(1, 100), new Range(200, 300) };
      Range[] exclude = new Range[] { new Range(25, 75), new Range(250, 280), new Range(90, 210) };
      foreach (Range r in exclude) {
        items = r.RemoveFrom(items).ToArray();
      }
          foreach (Range r in items) {
        Console.WriteLine("{0} - {1}", r.Start, r.End);
      }
      

      输出:

      1 - 25
      75 - 90
      210 - 250
      280 - 300
      

      【讨论】:

        【解决方案5】:

        您需要遍历禁止范围并在此过程中迭代创建有效范围。

        public List<Range> getValidRanges(Range total, List<Range> banned)
        {
          List<Range> valid = new ArrayList<Range>();
          int start = total.getStartTime();
          for(Range range: banned)
           {
             valid.add(new Range(start,banned.getStart()));
             start = banned.getEnd();
           }
           valid.add(new Range(start,total.getEnd()));
           return valid;
        }
        

        【讨论】:

        • 这段代码在任何情况下都不是有效的 C#。
        • 这很明显,但是从 java 转换为 c# 很容易,答案更多的是关于逻辑
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-09-23
        • 2011-11-06
        • 2012-10-10
        • 1970-01-01
        • 2022-01-10
        • 2015-03-14
        • 2010-11-02
        相关资源
        最近更新 更多