如何检查重叠并继续计算向前移动的未计算元素的总和(锯齿状数组)

How to check for overlaps and continue to count sum for the unaccounted elements moving forward (jagged array)

例如我有这个数组,稍后我需要在其中搜索:

private static readonly decimal[] ArrayWithFiveElements = { 0.1m, 0.2m, 0.3m, 0.4m, 0.5m };

然后我有一个范围数组,用于定义要搜索的元素:

            decimal[][] ranges =
            {
                new[] { 0.1m, 0.2m },
                new[] { 0.4m, 0.5m },
                new[] { decimal.Zero, decimal.One },
            };

现在我的代码应该做的是 return 匹配范围标准的元素的出现次数。现在,如果我尝试在没有最后一个数组的情况下计算这些范围,我将得到 4:0.1m、0.2m、0.4m 和 0.5m,但是如果我们尝试用最后一个(与前两个数组重叠)计算它,我将得到结果 9:0.1m、0.2m、0.4m、0.5m、0.1m、0.2m、0.3m、0.4m 和 0.5m。我想要的结果是 5: 0.1m, 0.2m, 0.3m, 0.4m, 0.5m .

我如何计算整个数组,如果数组与先前数组中的某些元素重叠,它会忽略它们,如果有未计算的元素,它会添加到计数中,而不是多次添加所有元素重叠。

到目前为止,这是我的代码:

        public static int GetDecimalsCount(decimal[] arrayToSearch, decimal[][] ranges)
        {
            if (arrayToSearch is null)
            {
                throw new ArgumentNullException(nameof(arrayToSearch));
            }
            else if (ranges is null)
            {
                throw new ArgumentNullException(nameof(ranges));
            }
            else
            {
                for (int x = 0; x < ranges.Length; x++)
                {
                    if (ranges[x] is null)
                    {
                        throw new ArgumentNullException(nameof(ranges));
                    }
                    else if ((ranges[x].Length > 0 && ranges[x].Length < 2) || ranges[x].Length > 2)
                    {
                        throw new ArgumentException(null);
                    }
                }

                int sum = 0;
                for (int i = 0; i < arrayToSearch.Length; i++)
                {
                    for (int j = 0; j < ranges.Length; j++)
                    {
                        if (ranges[j].Length == 0)
                        {
                            continue;
                        }
                        else if (arrayToSearch[i] >= ranges[j][0] && arrayToSearch[i] <= ranges[j][1])
                        {
                            sum++;
                        }
                    }
                }

                return sum;
            }
        }

有很多方法可以做到这一点,一种是使用 Any

public static int GetDecimalsCount(decimal[] arrayToSearch, decimal[][] ranges)
{
   if (arrayToSearch == null) throw new ArgumentNullException(nameof(arrayToSearch));
   if (ranges == null) throw new ArgumentNullException(nameof(ranges));
   if (ranges.Any(x =>x?.Length != 2)) throw new ArgumentException("Invalid ranges",nameof(ranges));

   return arrayToSearch.Sum(item =>
         ranges.Any(range =>
            item >= range[0] &&
            item <= range[1]) ? 1 : 0);
}

Full Demo Here

您也可以使用范围记录来省去一些麻烦

给定

public record Range(decimal From, decimal To)
{
   public bool Check(decimal value) => value >= From && value <= To;
}

例子

public static int GetDecimalsCount(decimal[] arrayToSearch, Range[] ranges)
{
   if (arrayToSearch == null) throw new ArgumentNullException(nameof(arrayToSearch));
   if (ranges == null) throw new ArgumentNullException(nameof(ranges));

   return arrayToSearch.Sum(item => ranges.Any(range => range.Check(item)) ? 1 : 0);
}

用法

var ranges = new Range[]
{
   new( 0.1m, 0.2m ),
   new(0.4m, 0.5m),
   new(decimal.Zero, decimal.One)
};

如果你需要在循环中这样做

public static int GetDecimalsCount(decimal[] arrayToSearch, decimal[][] ranges)
{
   if (arrayToSearch == null) throw new ArgumentNullException(nameof(arrayToSearch));
   if (ranges == null) throw new ArgumentNullException(nameof(ranges));
   if (ranges.Any(x => x?.Length != 2)) throw new ArgumentException("Invalid ranges", nameof(ranges));

   var sum = 0;

   foreach (var item in arrayToSearch)
      foreach (var range in ranges)
         if (item >= range[0] && item <= range[1])
         {
            sum++;
            break;
         }

   return sum;
}