Как я могу удалить определенные DataRows в цикле строк DataTable, которые соответствуют пользовательскому условию - скажем, строки, имеющие индекс четного числа -? (Без использования LINQ)
Спасибо
Как я могу удалить определенные DataRows в цикле строк DataTable, которые соответствуют пользовательскому условию - скажем, строки, имеющие индекс четного числа -? (Без использования LINQ)
Спасибо
Это зависит от того, что вы подразумеваете под словом "удалить".
Если вы хотите пометить их как удаленные, просто вызовите метод Delete()
для каждой строки, когда вы посещаете ее в своем цикле. Затем вам нужно вызвать AcceptChanges()
в таблице данных, чтобы завершить удаление - предположительно после того, как вы обновите свою базу данных (если она задействована).
foreach( DataRow row in someTable.Rows )
{
if( /* your condition here */ )
row.Delete();
}
someTable.AcceptChanges();
Если вы имеете в виду удалить его из DataTable, вам нужно сделать это в два прохода:
List<DataRow> rowsToDelete = new List<DataRow>();
foreach( DataRow row in someTable.Rows )
{
if( /* your condition here */ )
{
rowsToDelete.Add( row );
}
}
foreach( DataRow row in rowsToDelete )
{
someTable.Rows.Remove( row );
}
Стоит отметить, что вы всегда можете использовать первый метод для удаления строк, поскольку пометка строк как Deleted
и последующее принятие изменений автоматически удалит их из таблицы. Но иногда более понятно и эффективно просто удалить объекты DataRow
из коллекции Rows
.
Remove()
не рекомендуется в цикле foreach
, так как функция изменяет состояние коллекции.
- person Mstislav Toivonen; 19.03.2015
Попробуйте что-то вроде этого примера
DataTable table = new DataTable();
table.Columns.Add("Foo",typeof(int));
for (int i = 0; i < 10; i++)
table.Rows.Add(i);
for (int i = table.Rows.Count -1; i >=0; i--)
{
// sample removes all even foos
if ((int)table.Rows[i]["Foo"] % 2 == 0)
table.Rows.RemoveAt(i);
}
i++
внутри цикла for и увеличиваете его только при отсутствии удаления. if (...) remove() else i++
- person CuppM; 26.05.2010
Если вам нужно более короткое решение, чем предложенное выше, попробуйте перебрать список результатов и использовать лямбду, например sub(x)
, чтобы удалить каждую из этих строк.
dt.Select("Column1 > 0").ToList.ForEach(Sub(x) dt.Rows.Remove(x))
Другой способ
DataRow[] DrArrCheck = DataTableName.Select("ID > 0");
foreach(DataRow DrCheck in DrArrCheck)
{
DataTableName.Rows.Remove(DrCheck);
}
Чтобы удалить несколько строк (например, 50 000 из 100 000), гораздо быстрее скопировать базу данных, чем выполнять datatable.Rows.Remove(row) или row.Delete(). Например:
DataRow[] rowsToKeep = datatable.Select("ID > 50000");
DataTable tempDataTable= rowsToKeep.CopyToDataTable;
dataTable.Clear();
dataTable.Merge(tempDataTable);
tempDataTable.Dispose();
попробуйте перебрать результат Select(). Это очень похоже на другие ответы, но я считаю его самым прямым
DataRow[] r = table.Select();
for (int i = 0; i < r.Length; i++)
{
if (i % 2 == 0)
r[i].Delete();
}
Я всегда использовал "двухэтапный" подход Л.Бушкина и в конце концов решил, что стоит написать для него функцию:
public delegate bool DataRowComparer(DataRow dr);
public static void RemoveDataRows(DataTable table, DataRowComparer drc)
{
List<DataRow> RowsToRemove = new List<DataRow>();
foreach (DataRow dr in table.Rows)
if (drc(dr))
RowsToRemove.Add(dr);
foreach (DataRow dr in RowsToRemove)
table.Rows.Remove(dr);
}
И теперь я могу удалять строки одной строкой кода (например):
RemoveDataRows(dt, row => row["StringVal"].ToString() == "B" && (Int16)(row["NumberVal"]) >= 4);
В случае, если это поможет кому-то...
(И приветствуются любые способы дальнейшего сокращения.)
Вот как я это делаю.
for (int i = RowNumber.Count - 1; i >= 0; i--)
{
dt.Rows.RemoveAt(Int32.Parse(RowNumber[i]));
}
missingNotesGV.DataSource = dt;
missingNotesGV.DataBind();
Важно выполнять цикл for в обратном порядке, иначе вы получите ошибки, если будете удалять строки в конце в дополнение к строкам в других местах.
Вот как я это сделал, когда столкнулся с этой проблемой.
Dim index As Integer = 0
Dim count As Integer = resultsDT.Rows.Count - 1
For i As Integer = 0 To count
If resultsDT.Rows(index).Item("something") = "something" Then
resultsDT.Rows(index).Delete()
resultsDT.AcceptChanges()
index = index - 1
End If
index = index + 1
i = i + 1
Next
попробуй это
foreach(DataRow oRow in YourDataTable.Rows)
{
if ("Check You Condition")
{
YourDataTable.Rows.Remove(oRow);
}
}