C#函数,用于在特定日期找不到值时分割日期范围

时间:2019-07-16 14:57:59

标签: c# date range

我有一个日期范围为字符串的列表(例如'2019-05-01','2019-05-02','2019-05-05'...)和相同的数组包含布尔值的长度。

我需要对照布尔值区域中日期的对应值检查日期范围内的每一天,对于值为FALSE的任何一天,请从日期范围中删除日期并将其分为两个范围找不到值。

我一直在寻找适合这种模式的算法,但没有找到能在删除日期后拆分日期范围的算法。

List<Tuple<string, string>> ranges = new List<Tuple<string, string>>();

List<string> dt_range = new List<string>() { "2019-05-01", "2019-05-02", "2019-05-03", "2019-05-04", "2019-05-05", "2019-05-06" };
var valid = new bool[dt_range.Count];
valid[0] = true;
valid[1] = true;
valid[2] = false;
valid[3] = false;
valid[4] = true;
valid[5] = true;

for(var i = 0; i < dt_range; i++)
{
    if(valid[i] == true)
    {
        // Continue checking days
    }
    else if (valid[i] == false)
    { 
        // remove this day from date range, and create 
        // date range prior and following this, while
        // continuing to check for the rest of the days
    }
 }

因此,如果在2019-05-03中该值为FALSE,则该范围将细分为(2019-05-01,2019-05-02)和(2019-05-04,2019-05-05) ,2019,05-06),并将继续检查第二个范围,如有需要,请分拆。第一个范围(2019-05-01,2019-05-02)将添加到范围列表>中,而第二个范围需要继续进行验证,然后才能添加到范围列表中。

我在解决此问题方面遇到了精神障碍,我们将不胜感激。

5 个答案:

答案 0 :(得分:1)

如果我对要求的理解是正确的,那么下面的代码可以解决您的第一级问题。

 List<string> dt_range = new List<string>() { "2019-05-01", "2019-05-02", "2019-05-03", "2019-05-04", "2019-05-05", "2019-05-06" };

        var valid = new bool[dt_range.Count];
        valid[0] = true;
        valid[1] = true;
        valid[2] = false;
        valid[3] = false;
        valid[4] = true;
        valid[5] = true;

        List<List<string>> FinalRange = new List<List<string>>();

        for (var i = 0; i <= valid.Length-1; i++) {

            List<string> Splitted_Date_Range = new List<string>();
            if (!valid[i]) {
                for (int j = 0; j <i; j++) {
                    Splitted_Date_Range.Add(dt_range[j]);
                }
                for (int j = i + 1; j <= valid.Length - 1; j++) {
                    Splitted_Date_Range.Add(dt_range[j]);
                }
            }

            if (Splitted_Date_Range.Count > 0) {
                FinalRange.Add(Splitted_Date_Range);
            }
        }

我编写的循环用于核心级别的实现示例,可用于进一步的日期拆分。

答案 1 :(得分:1)

我同意@juharr的观点,认为会有更好的数据结构来解决您的问题,我也强烈建议使用DateTime存储日期,而不是string。但是,使用您提供的示例,下面有一个解决方案。基本上,您在最后一个有效元素(我称为previous)上保留一个标记,然后在遇到无效元素时对其进行更新。

List<Tuple<string, string>> ranges = new List<Tuple<string, string>>();

List<string> dt_range = new List<string>() { "2019-05-01", "2019-05-02", "2019-05-03", "2019-05-04", "2019-05-05", "2019-05-06" };
var valid = new bool[dt_range.Count];
valid[0] = true;
valid[1] = true;
valid[2] = false;
valid[3] = false;
valid[4] = true;
valid[5] = true;

string previous = dt_range.First();
for (int i = 0; i < dt_range.Count; i++) {
    if (!valid[i]) {
        if (previous != dt_range[i]) {
            ranges.Add(new Tuple<string, string>(previous, dt_range[i - 1]));
        }
        previous = dt_range[i + 1];
    }
}

// capture last range
ranges.Add(new Tuple<string, string>(previous, dt_range.Last()));

我从中获得的输出是两个范围,我相信它们与您想要的输出相匹配。

  

(2019-05-01,2019-05-02)

     

(2019-05-05,2019-05-06)

答案 2 :(得分:1)

将我的帽子扔进戒指,并假设您不需要空白范围,但想要任何余量,我认为它应该看起来像这样:

         var ranges = new List<List<string>>();

         var dt_range = new List<string> {"2019-05-01","2019-05-02","2019-05-03","2019-05-04","2019-05-05","2019-05-06"};
         var validDates = new[] {true, true, false, false, true, true};

         int i = 0;
         int startPos = 0;
         foreach (var valid in validDates)
         {
            if (!valid)
            {
               if ((i-startPos) > 0 )
                  ranges.Add(dt_range.Skip(startPos).Take(i - startPos).ToList());
               startPos = i + 1;
            }

            i++;
         }
         // Handle any remaining dates
         if (startPos < i)
            ranges.Add(dt_range.Skip(startPos).Take(i - startPos).ToList());

答案 3 :(得分:1)

只有一个循环就可以了

List<Tuple<string, string>> ranges = new List<Tuple<string, string>>();
string str1 = null;
string str2 = null;
for (int i = 0; i < dt_range.Count; i++)
{
    if (valid[i])
    {
        if (str1 == null)
        {
            str1 = dt_range[i];
        }
        str2 = dt_range[i];
    }
    else
    {
        if (str1 != null)
        {
            ranges.Add(Tuple.Create(str1, str2));
        }
        str1 = null;
    }
}
if (str1 != null)
{
    ranges.Add(Tuple.Create(str1, str2));
}

答案 4 :(得分:0)

我会用另一种方式解决这个问题,Linq:

var groupedRange = dtRange.GroupBy(g => valid[dtRange.IndexOf(g)] );

或者举一个完整的例子:

List<string> dtRange = new List<string>() {"2019-05-01","2019-05-02","2019-05-03","2019-05-04","2019-05-05","2019-05-06"};
    var valid = new bool[dtRange.Count];
    valid[0] = true;
    valid[1] = true;
    valid[2] = false;
    valid[3] = false;
    valid[4] = true;
    valid[5] = true;

    var groupedRange = dtRange.GroupBy(g => valid[dtRange.IndexOf(g)] );

    foreach(var gr in groupedRange)
    {
       foreach(var row in gr)
       {
           Console.WriteLine(gr.Key + " " + row);
       }
    }

您最终得到一个包含两个列表的新对象。

输出为:

True 2019-05-01
True 2019-05-02
True 2019-05-05
True 2019-05-06
False 2019-05-03
False 2019-05-04