38

データ テーブルからいくつかの行を削除する必要があります。コレクションを反復処理中に変更するのはよくないと聞いたことがあります。したがって、行が削除の要求を満たしているかどうかを確認してから削除済みとしてマークする for ループの代わりに、最初にデータ テーブルを反復処理してリスト内のすべての行を追加し、次にリストを反復処理してマークを付ける必要があります。削除する行。この理由は何ですか? (行リストを使用する代わりに) どのような代替手段がありますか?.

4

8 に答える 8

88

リストを逆方向に反復することは、より良いアプローチのように思えます。なぜなら、要素を削除して他の要素を「ギャップに陥らせる」場合、それらをすでに見ているため問題にならないからです。また、カウンター変数が .Count よりも大きくなることを心配する必要はありません。

        List<int> test = new List<int>();
        test.Add(1);
        test.Add(2);
        test.Add(3);
        test.Add(4);
        test.Add(5);
        test.Add(6);
        test.Add(7);
        test.Add(8);
        for (int i = test.Count-1; i > -1; i--)
        {
            if(someCondition){
                test.RemoveAt(i);
            }
        }
于 2008-11-21T14:02:28.840 に答える
33

@bruno コードを使用して、逆方向に実行します。

逆方向に移動しても、欠落している配列インデックスがループの順序に干渉しないためです。

var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 });

for (int i = l.Count - 1; i >= 0; i--)
    if (l[i] % 2 == 0)
        l.RemoveAt(i);

foreach (var i in l)
{
    Console.WriteLine(i);
}

しかし、真剣に、最近では、LINQ を使用します。

var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 });

l.RemoveAll(n => n % 2 == 0);
于 2008-11-22T06:19:38.057 に答える
18

for単純なループを使用すると、コレクションから要素を削除できます。

次の例を見てください。

        var l = new List<int>();

        l.Add(0);
        l.Add(1);
        l.Add(2);
        l.Add(3);
        l.Add(4);
        l.Add(5);
        l.Add(6);

        for (int i = 0; i < l.Count; i++)
        {
            if (l[i] % 2 == 0)
            {
                l.RemoveAt(i);
                i--;
            }
        }

        foreach (var i in l)
        {
            Console.WriteLine(i);
        }
于 2008-11-21T11:29:44.513 に答える
5

DataTable を使用していて、テーブル アダプターを使用して変更をサーバーに保持できるようにする必要があるため (コメントを参照)、行を削除する方法の例を次に示します。

DataTable dt;
// remove all rows where the last name starts with "B"
foreach (DataRow row in dt.Rows)
{
    if (row["LASTNAME"].ToString().StartsWith("B"))
    {
        // mark the row for deletion:
        row.Delete();
    }
}

行に対して delete を呼び出すと、RowState プロパティが Deleted に変更されますが、削除された行はテーブルに残ります。変更をサーバーに永続化する前にこのテーブルを操作する必要がある場合 (テーブルの内容から削除された行を差し引いたものを表示する場合など)、このように反復するときに各行の RowState を確認する必要があります。 :

foreach (DataRow row in dt.Rows)
{
    if (row.RowState != DataRowState.Deleted)
    {
        // this row has not been deleted - go ahead and show it
    }
}

コレクションから行を削除すると (ブルーノの回答のように)、テーブル アダプターが破損するため、通常は DataTable で行うべきではありません。

于 2008-11-21T13:10:29.447 に答える
3

while ループはこれを処理します。

int i = 0;
while(i < list.Count)
{
    if(<codition for removing element met>)
    {
        list.RemoveAt(i);
    }
    else
    {
        i++;
    }
}
于 2008-11-21T11:44:58.120 に答える
3

chakrit のソリューションは、ラムダ式ではなくデリゲートを使用して .NET 2.0 (LINQ/ラムダ式なし) をターゲットにしている場合にも使用できます。

public bool IsMatch(int item) {
    return (item % 3 == 1); // put whatever condition you want here
}
public void RemoveMatching() {
    List<int> x = new List<int>();
    x.RemoveAll(new Predicate<int>(IsMatch));
}
于 2008-12-24T04:01:46.260 に答える
2

あなたが言ったように、それを繰り返しながらリストを削除または追加すると、リストが壊れる可能性があります。

問題を解決するために、私はよく 2 つのリストのアプローチを使用しました。

ArrayList matches = new ArrayList();   //second list

for MyObject obj in my_list
{

    if (obj.property == value_i_care_about)
        matches.addLast(obj);
}

//now modify

for MyObject m in matches
{
    my_list.remove(m); //use second list to delete from first list
}

//finished.
于 2008-11-21T11:54:30.097 に答える
0

列挙しているコレクションからアイテムを削除する必要がある場合、通常は逆に列挙します。

于 2008-11-22T05:41:58.040 に答える