Safely remove list from list in loop - c#

I am iterating through all the list in mainlist and if a specific condition occur. I want to remove that specific list.
It is not working.
for (int i = 0; i < mainList.Count; i++)
{
if (mainList[i].Dead == true) //
{
mainList.removeAt(i);//what will be affect on mainList.Count;
}
}

mainList.RemoveAll(x => x.Dead);

The way you constructed your for loop, it will only work if mainList.Count stays constant, but you are removing elements during your loop. Do you understand why that is a problem? Whenever you remove an element you end up skipping the check of the element after it.
I think you could use foreach and mainList.remove but I'm not sure. Another solution is to just make your loop count downwards:
for (int i = mainList.Count-1; i >= 0; i--)
{
if (mainList[i].Dead == true)
{
mainList.removeAt(i);
}
}

You will not be able to do that since you are altering the length of the list when you are doing so. I would do it like this instead:
var newList = mainList.Where(y => !y.Dead).ToList();

How to modify or delete items from an enumerable collection while iterating through it in C#
http://bytes.com/topic/c-sharp/answers/238241-how-do-you-modify-array-while-iterating-through

Related

Changing an FSharpList in C#

FSharpList<FSharpList<int>> newImageList;
FSharpList<int> row;
for(int i = 0; i < CurrentImage.Header.Height)
{
row = PPMImageLibrary.GrayscaleImage(CurrentImage.ImageListData);
newImageList.Head = row;
}
Above I'm trying to take a int list list and set each index to row which is a int list. Obviously I can't do it with .Head, and if I could it would only change the first index. I'm wondering how I could possibly make this work, I'm having a hard time getting any index of newImageList in the first place.
FSharpList is an immutable list. Therefore you cannot assign its Head and Tail properties something. However, you can try adding your FSharp list into a generic C# List or any collection that inherits an IEnumerable. For example from your code:
List<int> newImageList = new List<int>();
for(int i = 0; i < CurrentImage.Header.Height)
{
newImageList.AddRange(PPMImageLibrary.GrayscaleImage(CurrentImage.ImageListData)); // I am assuming your GrayscaleImage method might return multiple records.
}
I hope this helps.

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
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));
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;
}
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();
How about this:
foreach (ListItem li in sp_list.Items) {
if (current.Contains(li.Text)) {
current.Remove(li.Text);
}
}
Put a break statement after the RemoveAt so you don't remove that item again.
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.

How to delete many items in listbox?

how to delete from listbox ?
deleting many indexes at the same time
Note that im using list of car types with their details
the objects in the listBox have car type cost rate
Update: If you want to remove all selected items as commented:
foreach (int i in listBox1.SelectedIndices)
listBox1.Items.RemoveAt(i);
If you want to delete all items instead, use Clear:
listBox1.Items.Clear();
if you want to remove at a specific index, use RemoveAt:
listBox1.Items.RemoveAt(0);
or in a loop:
for(int i = 0; i < listBox1.Items.Count; i++)
listBox1.Items.RemoveAt();
if you want to remove a speicific item, use Remove:
Car car = (Car) listBox1.Items[0];
listBox1.Items.Remove(car);
You have to use loop.
Something like this:
List<int> indexesToDelete = new List<int>();
// add items you want to remove to List like this:
indexesToDelete.Add(1);
indexesToDelete.Add(2);
indexesToDelete.Add(4);
// loop will execute code inside inside for all items added to list
foreach (int indexToDelete in indexesToDelete)
{
listbox1.RemoveAt(indexToDelete);
}
Edit: itemsToDelete renamed to indexesToDelete in code.

Remove multiple items from observablecollection in silverlight

how can i remove multiple items from observablecollection in silverlight.in my project i have one datagrid populating more than one items.in every row contain one checkbox also.if i select more than one row by selecting checkbox and click delete button ,i want to delete all the item from the collection.
public void delete(object parameter)
{
foreach (var x in Book)
{
if (x.Ischeck == true)
{
Book.Remove(x);
}
}
}
it cause error.can't change observablecollection
You can use below mentioned code snippet instead:
foreach (var x in Book.ToList())
{
if (x.Ischeck)
{
Book.Remove(x);
}
}
OR
for (int i = Book.Count - 1; i >= 0; i--)
{
if (Book[i].Ischeck)
{
Book.RemoveAt(i);
}
}
I assume that the error message is a bit different. To be more precise, it is:
Collection was modified; enumeration operation may not execute.
To work around this problem, one possible solution is this:
foreach (var itemToRemove in Book.Where(x => x.Ischeck).ToList())
{
Book.Remove(itemToRemove);
}
This will get all items you want to remove and put them into a new list. When you now remove items from Book you are not disturbing the list you are currently iterating over as this is an independent instance.
Using Where before calling ToList reduces the number of references you copy to the new list to only those that really need to be copied.
Simply get a list of the objects contained first:
public void delete(object parameter)
{
foreach (var x in Book.ToList())
{
if (x.Ischeck == true)
{
Book.Remove(x);
}
}
}
The reason for this is that you can't remove elements from an observable collection while you're enumerating the elements. By calling ToList() you enumerate the whole collection first, store it in a list and then check what to remove.

Foreach doesn't go through all items?

I have this code:
foreach (var item in ListView1.Items)
{
ListView1.Items.Remove(item);
ListView21.Items.Add(item);
}
the loop stops at half of the items?
Any idea?
EDIT
Well, maybe it's my mistake, I need to clarify that this is UltraListView control from Infrajistics, where I can't add item to another list unless I remove it or clone it from the original list.
But thanks, most of the comments regarding do not modify the list within the loop were correct, so this code works:
foreach (var item in listView1.Items)
{
var i = item.Clone(true);
listView2.Items.Add(i);
}
listView1.Items.Clear();
Thanks,
You cannot modify iterated collection, it should die with exception (or in undefined behavior).
Try making a copy of the array:
foreach (var item in ListView1.Items.ToArray())
{
ListView1.Items.Remove(item);
ListView21.Items.Add(item);
}
EDIT:
in fact, your example code can be achieved by writing:
ListView21.Items.AddRange(ListView1.Items);
ListView1.Items.Clear();
(which in fact isn't EXACTLY what you are doing, but gives the same result and I think it won't bother you having the same content in both listviews for a moment). The latter is supported since .NET2.0, first solution requires linq, and therefore .NET3.5.
You are modifying the collection you are looping through. Try using a for statement from top to bottom (from the item with the highest index to 0).
for (int i = ListView1.Items.Count - 1; i >= 0; i--)
{
var item = ListView1.Items[i];
ListView1.Items.Remove(item);
ListView21.Items.Insert(0, item);
}
It will cause a runtime exception, complaining that you cannot modify the collection while iterating through it. You have to use for loop instead.
for(int index = Items.Count; index > 0; index--)
{
.......
// use Add and RemoveAt
}
EDIT : As mentioned by others. If you just need to move items from one collection to the other. AddRange and Clear will be better.
Do you get any exception or error message? Looping in a collection and remove items from the same collection is always a bad idea.
This looks like the WinForms list view control, so:
ListViewItem[] items = ListView1.Items.ToArray();
ListView1.Items.Clear();
ListView21.Items.AddRange(items);
Why just not CopyTo() to new list and then Clear() items?
You are looping through all items, removing all of them, then adding them to another list. As others have commented, you cannot remove items from a list in a for-each. Why not looping through all items to add them to your other list, and then remove them all in one go?
foreach (var item in ListView1.Items)
{
ListView21.Items.Add(item);
}
ListView1.Items.Clear(); // remove all
PS: is this an ASP.NET listview or a WinForms listview?
That's because you're changing the collection inside the loop.
Use a normal for loop as follows:
for(int i=0; i < ListView1.Items.Count-1; i++)
{
ListView21.Items.Add(ListView1.Items[i]);
ListView1.Items.RemoveAt(i);
}

Categories

Resources