カスタム条件を満たすDataTable行のループ内の特定のDataRowsを削除するにはどうすればよいですか?たとえば、偶数のインデックスを持つ行を削除できますか?(LINQを使用せずに)
ありがとう
'delete'の意味によって異なります。
それらを削除済みとしてマークする場合Delete()
は、ループ内でアクセスするときに各行のメソッドを呼び出すだけです。次に、データテーブルを呼び出しAcceptChanges()
て、削除を完了する必要があります。おそらく、データベースを更新した後です(データベースが関係している場合)。
foreach( DataRow row in someTable.Rows )
{
if( /* your condition here */ )
row.Delete();
}
someTable.AcceptChanges();
DataTableから削除する場合は、次の2つのパスで削除する必要があります。
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
この例のようなものを試してください
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);
}
上で提案したものよりも短い解決策が必要な場合は、結果のリストをループして、ラムダ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);
}
public static void DeleteRowsFromDataTable(DataTable dataTable, string columnName, string columnValue)
{
IEnumerable<DataRow> dataRows = (from t in dataTable.AsEnumerable()
where t.Field<string>(columnName) == columnValue
select t);
foreach (DataRow row in dataRows)
dataTable.Rows.Remove(row);
}
複数の行(たとえば、100,000のうち50,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();
}
私は常にLBushkinの「2フェーズ」アプローチを使用していましたが、最終的に、そのための関数を作成する価値があると判断しました。
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);
}
そして今、私は1行のコードで行を削除することができます(例えば):
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);
}
}