C# Функция делегата всегда разрешает true для половины набора данных. - PullRequest
0 голосов
/ 26 февраля 2020

Я пытаюсь написать метод, который разбивает DataTable на основе заданного условия (делегат). Моя проблема в том, что условие, которое я использую, всегда разделяет ровно половину DataTable. Кажется, что условие разрешается истинным для половины DataRows, даже если NO DataRows не должно принимать значение true.

Метод выглядит следующим образом:

private DataTable PartitionDataTable(DataTable data, Func<DataRow, bool> condition) {

DataTable removedRows = data.Clone();
for(int i = 0; i < data.Rows.Count; i++) {
  if(condition(data.Rows[i])){
    removedRows.ImportRow(data.Rows[i]);
    data.Rows.Remove(data.Rows[i]);
  }
}
  return removedRows;
}

Я вызываю этот метод, используя это условие:

DataTable removed = PartitionDataTable(data, (row => DateTimeOffset.Parse(row["timestamp"].ToString()) < baselineTimestamp);

Если максимальная / максимальная временная метка в объекте данных (DataTable) на несколько минут раньше, чем 'baselineTimestamp', определенная с помощью data.Compute("max([timestamp])", String.Empty), то половина записей по-прежнему разделяется и удаляется, если ни одна из них должно быть потому, что все они

Понятия не имею, что происходит. Пожалуйста, помогите мне. Цель состоит в том, чтобы разбить DataRows с временными метками ранее заданного (с точностью до миллисекунды).

Ответы [ 3 ]

0 голосов
/ 26 февраля 2020

Вы удаляете строки во время итерации по набору данных. Таким образом, если i=2, то вы удаляете строку 2, а строка 3 теперь становится строкой 2. Затем вы увеличиваете i, работая с новой строкой 3 (которая была строкой 4), поэтому вы пропускаете исходную строку 3 в целом.

Чтобы решить эту проблему, нужно выполнить итерацию в обратном направлении , поскольку смещенные строки - это те, которые вы уже обработали:

for(int i = data.Rows.Count-1; i >= 0; i--) {
  if(condition(data.Rows[i])){
    removedRows.ImportRow(data.Rows[i]);
    data.Rows.Remove(data.Rows[i]);
  }
}
  return removedRows;
}
0 голосов
/ 26 февраля 2020

Поскольку вы удаляете элементы из массива, вы должны двигаться назад. Если вы сделаете это вперёд, вы пропустите половину элементов, и именно поэтому вы получите половину из них обратно:

DataTable removedRows = data.Clone();
for(int i = data.Rows.Count-1; i >= 0 ; i--) {
  if(condition(data.Rows[i])){
    removedRows.ImportRow(data.Rows[i]);
    data.Rows.Remove(data.Rows[i]);
  }
}
  return removedRows;
}
0 голосов
/ 26 февраля 2020

Каждый раз, когда вы удаляете строку из data, она Rows.Count уменьшается.

Предположим, data содержит 10 строк в начале.

Вы увеличиваете i до 5, пока Вы удаляете 5 строк из data.

. На следующей итерации i равно 6, а data.Rows.Count равно 5, l oop завершается.

...