Заполнение списка значениями в диапазоне - PullRequest
0 голосов
/ 25 октября 2019

У меня есть список дат, как показано ниже:

2017-02-08 00:00:00.000
2017-02-08 00:00:00.000
NULL
2017-03-20 00:00:00.000
NULL
2017-03-20 00:00:00.000
NULL
NULL
2017-03-20 00:00:00.000
2017-02-08 00:00:00.000
NULL
NULL
NULL
2017-02-08 00:00:00.000

Это должно быть заполнено следующим образом. то есть заполнить все даты, у которых есть похожие соседи, до 2 значений NULL.

2017-02-08 00:00:00.000
2017-02-08 00:00:00.000
NULL
2017-03-20 00:00:00.000
2017-03-20 00:00:00.000
2017-03-20 00:00:00.000
2017-03-20 00:00:00.000
2017-03-20 00:00:00.000
2017-03-20 00:00:00.000
2017-02-08 00:00:00.000
NULL
NULL
NULL
2017-02-08 00:00:00.000

Вот то, что я строю до сих пор. Любая идея ценится

DateTime? latestDate = null;

foreach (var date in dates)
{
    if (date == null)
    {
        latestDate = date;
    }
    else
    {
        date = latestDate;
    }
}

Ответы [ 3 ]

2 голосов
/ 25 октября 2019

Для упрощения, а не для разбора строк и сравнения дат.
Для того, чтобы иметь ясные mre , DateTime теперь int.
Live demo

Контрольный пример.

Основываясь на вопросе, у меня есть следующий контрольный пример:

//Input                           Expected Output
{ null, 1 },                    { null, 1 } 
{ null, null, 1 },              { null, null, 1 } 
{ null, null , null, 1 },       { null, null , null, 1 } 

{ 1, null, 1 },                 { 1, 1, 1 } 
{ 1, null, null, 1 },           { 1, 1, 1, 1 } 
{ 1, null, null, null, 1 },     { 1, null, null, null, 1 } 

{ 1, null, 2 },                 { 1, null, 2 } 
{ 1, null, null, 2 },           { 1, null, null, 2 } 
{ 1, null, null, null, 2 },     { 1, null, null, null, 2 } 

Код.

Здесь мы выигралине ищите оптимизации кода, минимального назначения переменных или сохранения последнего значения, которое мы только что прочитали. Мы остаемся рядом с тестовым набором.

for (int i = 0; i < input.Length - 1; i++)
{
    if (i == 0) { continue; } //First elment? Skip.
    if (input[i] != null) { continue; }// Already have a value? Skip.

    // First and last elment are safe.
    int? closestValueLeft = input[i - 1];
    int? closestValueRight = input[i + 1];

    // ####  CASE 1 #### : Left and right have value. 
    if (closestValueLeft != null && closestValueRight != null)
    {
        if (closestValueLeft == closestValueRight)
        {// both are the same. 
            input[i] = closestValueLeft;
        }
    }

    // ####  CASE 2 #### : Left and right don't have value. 
    else if (closestValueLeft == null && closestValueRight == null)
    {// Left and right have no value, Skip.
        continue;
    }

    // ####  CASE 3 #### : We have to move a bit to find 
    else
    {// Either left or right have a value but not both. We are gona move one step after the null. 
        if (closestValueLeft != null)
        { // Left is not null move right. 
            if (i + 2 < input.Length)// Array out of bound protection
            {
                closestValueRight = input[i + 2];
            }
        }
        else
        {// Right is not null, move left. 
            if (i - 2 > 0)// Array out of bound protection
            {
                closestValueLeft = input[i - 2];
            }
        }

        if (closestValueLeft == closestValueRight)
        {
            input[i] = closestValueLeft;
        }
    }
}
1 голос
/ 25 октября 2019

Я не проверял это, поскольку не воссоздал Список дат, но это (или что-то довольно близкое) должно сработать

if (dates.Count > 2)
{
      int i = 0;
      do
      {
          if (dates[i] != null && dates[i + 1] == null && dates[i + 2] == null && (i + 3 >= dates.Count || dates[i + 3] != null))
          {
              dates[i + 1] = dates[i];
              dates[i + 2] = dates[i];
              i += 3;
          }
          else i++;
      } while (i < dates.Count - 3);
  }

РЕДАКТИРОВАТЬ: Возможно, я неправильно понял исходное требование (см. Комментарий). Если это так, это может быть более подходящим

        if (dates.Count > 2)
        {
            int i = 0;
            do
            {
                if (dates[i] != null && dates[i + 1] == null && dates[i + 2] == dates[i])
                {
                    dates[i + 1] = dates[i];
                    i += 2;
                }
                else if (dates[i] != null && dates[i + 1] == null && dates[i + 2] == null && (i+3<dates.Count && dates[i + 3] == dates[i]))
                {
                    dates[i + 1] = dates[i];
                    dates[i + 2] = dates[i];
                    i += 3;
                }
                else i++;
            } while (i < dates.Count - 3);
        }
1 голос
/ 25 октября 2019

Если я понимаю вопрос, это решение:

foreach (var date in dates.Select((date, index) => new { date, index }))
{
    if (date.index - 2 < 0) continue;

    if (dates[date.index - 2].HasValue && 
        dates[date.index - 2].Value == date.date && 
       !dates[date.index - 1].HasValue)
    {
        dates[date.index - 1] = date.date;
    }
    else if (dates[date.index - 3].HasValue &&
             dates[date.index - 3].Value == date.date &&
            !dates[date.index - 1].HasValue &&
            !dates[date.index - 2].HasValue)
    {
        dates[date.index - 1] = date.date;
        dates[date.index - 2] = date.date;
    }
}

@ Drag and Drop thx хорошая идея

for (int index = 0; index < dates.Count(); index++)
{
    if (index - 2 < 0) continue;

    if (dates[index - 2].HasValue &&
        dates[index - 2].Value == dates[index] &&
       !dates[index - 1].HasValue)
    {
        dates[index - 1] = dates[index];
    }
    else if (index - 3 >= 0 &&
             dates[index - 3].HasValue &&
             dates[index - 3].Value == dates[index] &&
            !dates[index - 1].HasValue &&
            !dates[index - 2].HasValue)
    {
    dates[index - 1] = dates[index];
    dates[index - 2] = dates[index];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...