I don't usually develop on Windows but recently I have had to do a bit of work with C# and I'm trying to get my head around a few things. I've been looking through the MSDN but cant quite find what I'm looking for.
Anyway as I understand it a List is indexed, much like an array. However if I deleted an item at position X using RemoveAt() would it then shift all the items so that a new item now filled position X? Or would position X just be empty?
Also using Remove() seems fairly straight forward if you have a List of strings or integers, but if you have a list of objects is it possible to use Remove() to delete an item where an object field has a specific value?
For example
Say i have List where each car object has a make, model & color.
Could i do something along the lines of
cars.Remove(cars.color="red");
I'm sure that is horribly wrong but I am coming from a PHP background so im pretty confused about alot of the syntax at the moment.
Thanks
List<T> will not get holes.
Removing an item will shift all subsequent items up by one.
You can remove all items that match a condition by calling RemoveAll() with a lambda expression:
list.RemoveAll(o => o.Color == "Red");
if I deleted an item at position X using RemoveAt() would it then
shift all the items so that a new item now filled position X?
Yes.
if you have a list of objects is it possible to use Remove() to delete
an item where an object field has a specific value?
Yes, use the RemoveAll method:
cars.RemoveAll(c => c.color == "red");
When items are removed the spot is taken up by the next one. As lists are collections you can use lambda with remove all
Cars.RemoveAll( x=> x.colour == "red");
Will remove all re cars.
Related
I'm programming in Visual studio 2013 C#.
If listname.add is adding a number, so how to remove a number from a list?
The complement of "add" is not "subtract" for a list, it's "remove".
To remove an item with a specific value you can use the Remove method:
listname.Remove(value);
To remove an item at a specific index you can use the RemoveAt method:
listname.RemoveAt(index);
To remove multiple values you can use the RemoveAll method, which will remove all items that match a condition:
listname.RemoveAll(i => i == value);
Note that the Remove method will search through the list until it finds the value. If this is something that you do frequently, you might want to use differnt collection, like a HashSet<int> where removing a value is an O(1) operation instead of an O(n) operation.
thanks you all guys. Guffa solved it. you just need to enter "listname.Remove(value);" its my first question here. and I'm going to come back. for those who wondering- I'm developing A game. I I needed a list to set my levels system, thanks for your help!
I am trying to delete an item which is in a listbox "in a smart way". I found an alternative to my problem but I don't like it.
My program is a matrix calculator. All my matrices are in a dictionary and I "print" them in a listbox in the graphical interface.
My alternative is to delete all items in the listbox, remove the selected matrix in my dictionary and re-add all the matrices in the listbox.
So my problem is that I need to find the index of the item I want to delete, and delete it, but the var index is always equals to -1. I look for a solution and I found that i needed to override the methodes Equals(), GetHashCode() and maybe ToString(). I wonder if there is any better solution.
public static String Delete ()
{
String matrix = matches[0].Groups[2].ToString();
if (Calculatrice.listMatrix.ContainsKey(matrix))
{
Matrix m = Calculatrice.listMatrix[matrix];
int index = Calculatrice.mainWindow.ListBox_display.Items.IndexOf(m);
Calculatrice.mainWindow.ListBox_display.Items.RemoveAt(index);
Calculatrice.listMatrix.Remove(matrix);
return "Done!\n";
}
throw new Exception("The matrix does not exist.\n");
}
If you want to know my Regex, this is it: private static Regex delete_rgx = new Regex(#"^(delete)\((\w+)\)$");
I'm new to the StackOverflow community, and I will listen to all your suggestion for my problem and also for how to make a better question, explanation, etc.
The objects in ListBox_display are probably not the exact objects as in your listMatrix dictionary.
The IndexOf function will return the index of the specific object (just like you want) but in your case if the object in the dictionary is not the same object in the listbox you will get a -1.
Try populating the Listbox using listMatrix.Values
can I do this without looping through the whole list?
List<string> responseLines = new List<string>();
the list is then filled with around 300 lines of text.
next I want to search the list and create a second list of all lines that either start with "abc" or contain "xyz".
I know I can do a for each but is there a better / faster way?
You could use LINQ. This is no different performance-wise to using foreach -- that's pretty much what it does behind the scenes -- but you might prefer the syntax:
var query = responseLines.Where(s => s.StartsWith("abc") || s.Contains("xyz"))
.ToList();
(If you're happy dealing with an IEnumerable<string> rather than List<string> then you can omit the final ToList call.)
var newList = (from line in responseLines
where line.StartsWith("abc") || line.Contains("xyz")
select line).ToList();
Try this:
List<string> responseLines = new List<string>();
List<string> myLines = responseLines.Where(line => line.StartsWith("abc", StringComparison.InvariantCultureIgnoreCase) || line.Contains("xyz")).ToList();
The StartsWith and Contains shortcut - the Contains will only evaluate if the StartsWith is not satisfied. This still iterates the whole list, but of course there is no way to avoid that if you want to check the whole list, but it saves you from doing typing a foreach.
Use LINQ:
List<string> list = responseLines.Where(x => x.StartsWith("abc") || x.Contains("xyz")).ToList();
Unless you need all the text for some reason, it would be quicker to inspect each line at the time when you were generating the List and discard the ones that don't match without ever adding them.
This depends on how the List is loaded as well - that code is not shown. This would be effective if you were reading from a text file since then you could just use your LINQ query to operate directly on the input data using File.ReadLines as the source instead of the final List<string>.
var query = File.ReadLines("input.txt").
Where(s => s.StartsWith("abc") || s.Contains("xyz"))
.ToList();
LINQ works well as far as offering you improved syntax for this sort of thing (See LukeH's answer for a good example), but it isn't any faster than iterating over it by hand.
If you need to do this operation often, you might want to come up with some kind of indexed data structure that watches for all "abc" or "xyz" strings as they come into the list, and can thereby use a faster algorithm for serving them up when asked, rather than iterating through the whole list.
If you don't have to do it often, it's probably a "premature optimization."
Quite simply, there is no possible algorithm that can guarantee you will never have to iterate through every item in the list. However, it is possible to improve the average number of items you need to iterate through - sorting the list before you begin your search. By doing so, the only times you would have to iterate through the entire list would be when it is filled with only "abc" and "xyz."
Assuming that it's not practical for you to have a pre-sorted list by the time you need to search through it, then the only way to improve the speed of your search would be to use a different data structure than a list - for example, a binary search tree.
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Exception during iteration on collection and remove items from that collection
How to remove elements from a generic list while iterating around it?
Better way to remove matched items from a list
// tmpClientList is List<Client> type
if (txtboxClientName.Text != "")
foreach (Client cli in tmpClientList)
if (cli.Name != txtboxClientName.Text)
tmpClientList.Remove(cli);
Error: "Collection was modified; enumeration operation may not execute."
How can i remove items from the list, in some simple way, without saving indexes of these items in another list or array, and removing them in another place in the code. Tried also RemoveAt(index) but it's exactly the same situation, modifying when loop runs.
Move backwards through the list.. that way removing an item does not affect the next item.
for(var i=tmpClientList.Count-1;i>=0;i--)
{
if (tmpClientList[i].Name != txtboxClientName.Text)
tmpClientList.RemoveAt(i);
}
On a List<T>, there is a RemoveAll method that takes a delegate to indicate whether to remove the item. You can use it like this:
tmpCLientList.RemoveAll(cli => cli.Name != txtboxClientName.Text);
Either use a for/while loop, or tmpClientList.RemoveAll(a => a.Name == txtboxClientName.Text). As you didn't specify which c# version you are using, ymmw.
Don't use foreach. Use for and descend the list (i.e. start from the end), using RemoveAt.
So,
// tmpClientList is List<Client> type
if (txtboxClientName.Text != "")
foreach (int pos = tmpClientList.Length - 1; pos >= 0; pos--)
{
Client cli = tmpClientList[pos];
if (cli.Name != txtboxClientName.Text)
tmpClientList.RemoveAt(pos);
}
The problem is that you are trying the modify the list in a foreach iteration. Replace that with a for and you should be ok.
Also, since you seem to be using user input for the name, consider cleaning up the input a bit, at least with a Trim() to remove extra white spaces. If you don't, 'John ' and 'John' will be two different things.
Same for the initial != "" check.
You can create another list with the items you want to delete and iterate the new list to remove items from your "txtboxClientName" list.
Actually, foreach uses Enumerators to iterate through given Item-Collections. Going further the System.Collections.Generic.List<T> implements the IEnumarable-Interface to provide a Class, that knows how to iterate through the items of the list, i.e. the Enumerator. Now if you iterate through that list by using foreach the Enumerator keeps track of the current position, how to reach the next position and some other stuff. The internal logic could be something like storing the number of items in a variable n and then access all objects from 0 to n-1. As you may notice if any object is removed between the iteration steps we shall end in a NullReferenceException when the Enumerator tries to deliver the last object of the list. So to prevent any iteration failures, the list itself is not allowed to be modified during Enumeration.
Hope I was able to state that out at least a little bit comprehensively. :-)
If I have
List<String> text
how can I create a sub-list of all continious elements within a specific range e.g.
List<String> subList = /* all elements within text bar the first 2*/
Also are there any other useful List manipulation tips & tricks that might be useful?
This will work even without LINQ:
List<String> subList = text.GetRange(2, text.Count - 2);
Edit: Fixed a typo.
subList = text.Skip(2).ToList()
Skip(n) returns an IEnumerable<> with all elements except the first n.
When you really need a list after that, ToList() converts it back.
If you're on 3.5, then there are a lot of new and interesting methods available on List. Just check out the section 'Extension methods' here: http://msdn.microsoft.com/en-us/library/d9hw1as6.aspx