Mike91
Mike91

Reputation: 540

Removing an item from a list c#

I am having trouble with removing an item from a list in c#. My current code is below:

for (int i = current.Count - 1; i >= 0; i--)
    {
        foreach (ListItem li in sp_list.Items)
        {
            if (li.Text == current[i].uname)
            {
                current.RemoveAt(i);
            }
        }
    }

The aim of the code is to compare the existing items in a list box with newly added items so I know which items have just been added. So currently I am getting the current list box items from the database (they are stored here, it is a databound list box), entering these into a list and for each of the list items, comparing them with the items in a list box and if they match, remove the item from the list.

Therefore, in the end, if I add two new entries, the list should only be storing the two newly added values.

The code does not work as the first item is removed fine, but then, the value of i is greater than current.count - and therefore I get an out of range exception!

Could someone help me with this issue? Apologies about the confusing question, it's hard to explain! Thanks

Upvotes: 1

Views: 514

Answers (6)

Jodrell
Jodrell

Reputation: 35746

Your nesting is wrong, I think you wanted,

foreach (ListItem li in sp_list.Items)
{
    for (int i = current.Count - 1; i >= 0; i--)
    {
        if (li.Text == current[i].uname)
        {
            current.RemoveAt(i);
        }
    }
}

alternatively, use linq,

// For lookup performance.
var items = new HashSet(sp_list.Items.Select(i => i.text));

current = current.Where(c => !items.Contains(c.uname)).ToList();

Upvotes: 4

y62wang
y62wang

Reputation: 568

you can travel the list in reverse order and remove items using RemoveAt(i). also for efficiency purposes you may want to put the ListItem texts in a Set so you can don't have to loop though the sp_list.Items for each of your current items.

Upvotes: 0

djs
djs

Reputation: 230

Put a break statement after the RemoveAt so you don't remove that item again.

Upvotes: 0

Zev Spitz
Zev Spitz

Reputation: 15375

How about this:

foreach (ListItem li in sp_list.Items) {
    if (current.Contains(li.Text)) {
        current.Remove(li.Text);
    }
}

Upvotes: 3

Andrew Cooper
Andrew Cooper

Reputation: 32596

Once you've found the matching value, and removed it from the list, you want to break out of the inner loop to check the next item.

        if (li.Text == current[i].uname)
        {
            current.RemoveAt(i);
            break;
        }

Upvotes: 4

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236328

You can do it with Linq. Not sure if casting to ListItem needed (you can remove it)

current.RemoveAll(x => sp_list.Items.Cast<ListItem>()
                              .Any(li => li.Text == x.uname));

Upvotes: 8

Related Questions