2

文字列値のリストがあり、一部の値の前に xxx または XXX が含まれています。

xxxRed
xxxYellow
xxxxCareful with that axe Eugene!
xxxxxxdedicum aceasta frumoasa Melodia
xxxxLeaders
xxxxWorking Around - titles
XXXXXNothing To Fear
xxxxAvoiding standards
xxxFirst Aid

List<string> lstTitles = new List<string>();

これは私が試したものです

for (int i=0; i < lstTitles.Count; i++)
            {
                string title = lstTitles[i].ToLower().Trim();
                if (title[0] == 'x')
                {
                    lstTitles.Remove(lstTitles[i]);

                }
            }

私が抱えている問題は、すべての値ではなく、一部の値のみが削除されることです。

これらの値を削除するより良い方法はありますか?

4

6 に答える 6

10

RemoveAllメソッドを使用する

lstTitles.RemoveAll(s => s[0] == 'x' || s[0] == 'X');

StartsWith最初の文字を比較する代わりに使用したい場合があります。

lstTitles.RemoveAll(s => s.StartsWith("x",StringComparison.InvariantCultureIgnoreCase));
于 2013-06-06T11:15:23.567 に答える
3

私が抱えている問題は、すべての値ではなく、一部の値のみが削除されることです。

アイテムをスキップしているからです。を呼び出すRemove()と、次のアイテムは index になりますが、次のループでi増加します。i

リストのコピーを反復処理し、元の不要なアイテムを削除することで解決できます。

foreach (var item in lstTitles.ToList())
{
    if (item.StartsWith("x", StringComparison.InvariantCultureIgnoreCase))
    {
        lstTitles.Remove(item);
    }
}

これにはリストのコピーの作成が含まれますが、これはあまり役に立ちませんRemove()

したがって、for ループを逆にして、未処理のアイテムのインデックス作成を変更しない最後のアイテムを最初に削除することができます。

for (int i = lstTitles.Count - 1; i > 0; i--)
{
    if (lstTitles[i].StartsWith("x", StringComparison.InvariantCultureIgnoreCase))
    {
        lstTitles.RemoveAt(i);
    }
}

しかし、@I4V が指摘しているように、このロジックはすべて に既にList<T>.RemoveAll()含まれています。

于 2013-06-06T11:14:41.377 に答える
2

この方法で新しいリストを作成したほうがいいと思います

list = list
    .Where(i => ! i.StartsWith("xxx", StringComparison.InvariantCultureIgnoreCase))
    .ToList();

O(n)の複雑さがありますが、1つずつ削除しようとするとO(n ^ 2)になります。

于 2013-06-06T11:17:41.883 に答える
2

これは、スキップ値が原因です。

リストに ['xVal1', 'xVal2', 'val3', 'xVal4', 'val5'] が含まれているとします。最初iは 0 で、'xVal1' である list[0] を見て、それを削除します。

リストには [' xVal2 ', 'val3', 'xVal4', 'val5'] が含まれており、あなたiは 1 です。つまり、'val3' である list[1] を見ます。xVal2 を無視しました!

リストの後ろから始めて前に行くことができますが、削除する同一の値がある場合、潜在的なバグが残ります。

より短い方法は、LINQ を使用することです。

var newList = lstTitles.Where(title=>!title.StartsWith('xxx'))
于 2013-06-06T11:16:23.293 に答える
2

代わりに、を渡すことができるToLowerオーバーロードを使用する必要があります。StartsWithStringComparison.OrdinalIgnoreCase

次にList.RemoveAll、最も読みやすく、最も効率的で、最短のアプローチを使用します。

lstTitles.RemoveAll(s => s.TrimStart().StartsWith("x", StringComparison.OrdinalIgnoreCase));

デモ

于 2013-06-06T11:16:39.723 に答える