can't copy objects into new array - c#

I have an array filled with objects of a type I have declared myself (called ServiceUnit). I now want to filter out only some of the objects from this array and what I'm doing to acheive this is that I have a new array with the correct size and just try to copy the objects in to the new one.
ServiceUnit[] serviceUnits = ProductConfiguration.ServiceGuide.GetServiceUnits();
ServiceUnitType serviceUnitType = ProductConfiguration.ServiceGuide.GetServiceUnitType(guid);
int size = 0;
/* COUNT THE NUMBER OF OBJECTS ADHERING TO MY CRITERIA */
foreach (ServiceUnit unit in serviceUnits)
{
if (unit.ServiceUnitTypeAttributes[0].ServiceUnitType.Id == serviceUnitType.Id)
{
size++;
}
}
/* ARRAY TO STORE FILTERED OBJECTS BASED ON A CRITERIA */
ServiceUnit[] serviceUnitsFiltered = new ServiceUnit[size];
/* LOOP AND CHECK IF ADHERING TO CRITERIA, THEN COPY TO NEW ARRAY */
for(int i=0; i<serviceUnits.Length; i++){
if(serviceUnits[i].ServiceUnitTypeAttributes[0].ServiceUnitType == serviceUnitType){
serviceUnitsFiltered[i] = serviceUnits[i];
}
}
The problem I have is that the new array does have the right amount of objects in it, but they are not populated with the data from serviceUnits[i]. Instead they are just "nulled".
Any ideas on what might be wrong or how to solve it?

The bug is in this line:
serviceUnitsFiltered[i] = serviceUnits[i];
The index to serviceUnitsFiltered shouldn't be i but something else. Probably a new variable that is incremented every time you add something to serviceUnitsFiltered, like:
serviceUnitsFiltered[j++] = serviceUnits[i];
Also consider using LINQ, it's shorter (albeit a tiny bit slower):
serviceUnitsFiltered = serviceUnits.Where(x=>x.ServiceUnitTypeAttributes[0].ServiceUnitType == serviceUnitType).ToArray();

Why not just do...
ServiceUnit[] serviceUnits = ProductConfiguration.ServiceGuide.GetServiceUnits();
ServiceUnitType serviceUnitType = ProductConfiguration.ServiceGuide.GetServiceUnitType(guid);
serviceUnitsFiltered = serviceUnits.Where(unit=>unit.ServiceUnitTypeAttributes[0].ServiceUnitType.Id == serviceUnitType.Id).ToList();

You can do it much easier with LINQ:
serviceUnitsFiltered = serviceUnits.Where(su => su.ServiceUnitTypeAttributes[0].ServiceUnitType == serviceUnitType)
.ToArray();

You can use List<T> instead of using array :
/* LOOP AND CHECK IF ADHERING TO CRITERIA, THEN COPY TO NEW ARRAY */
List<ServiceUnit> serviceUnitsFiltered= new List<ServiceUnit>();
for(int i = 0; i < serviceUnits.Length; i++)
if(serviceUnits[i].ServiceUnitTypeAttributes[0].ServiceUnitType == serviceUnitType)
serviceUnitsFiltered.Add(serviceUnits[i]);
Or if you strictly need an array of ServiceUnit elements you can convert it using List<T>.ToArray() method
P.S.
LINQ is one line solution but it is slower than simple for loop with just one if(condition) expression...

Related

How to remove a scriptable object from a list of scriptable objects? [duplicate]

I am looking for a better pattern for working with a list of elements which each need processed and then depending on the outcome are removed from the list.
You can't use .Remove(element) inside a foreach (var element in X) (because it results in Collection was modified; enumeration operation may not execute. exception)... you also can't use for (int i = 0; i < elements.Count(); i++) and .RemoveAt(i) because it disrupts your current position in the collection relative to i.
Is there an elegant way to do this?
Iterate your list in reverse with a for loop:
for (int i = safePendingList.Count - 1; i >= 0; i--)
{
// some code
// safePendingList.RemoveAt(i);
}
Example:
var list = new List<int>(Enumerable.Range(1, 10));
for (int i = list.Count - 1; i >= 0; i--)
{
if (list[i] > 5)
list.RemoveAt(i);
}
list.ForEach(i => Console.WriteLine(i));
Alternately, you can use the RemoveAll method with a predicate to test against:
safePendingList.RemoveAll(item => item.Value == someValue);
Here's a simplified example to demonstrate:
var list = new List<int>(Enumerable.Range(1, 10));
Console.WriteLine("Before:");
list.ForEach(i => Console.WriteLine(i));
list.RemoveAll(i => i > 5);
Console.WriteLine("After:");
list.ForEach(i => Console.WriteLine(i));
foreach (var item in list.ToList()) {
list.Remove(item);
}
If you add ".ToList()" to your list (or the results of a LINQ query), you can remove "item" directly from "list" without the dreaded "Collection was modified; enumeration operation may not execute." error. The compiler makes a copy of "list", so that you can safely do the remove on the array.
While this pattern is not super efficient, it has a natural feel and is flexible enough for almost any situation. Such as when you want to save each "item" to a DB and remove it from the list only when the DB save succeeds.
A simple and straightforward solution:
Use a standard for-loop running backwards on your collection and RemoveAt(i) to remove elements.
Reverse iteration should be the first thing to come to mind when you want to remove elements from a Collection while iterating over it.
Luckily, there is a more elegant solution than writing a for loop which involves needless typing and can be error prone.
ICollection<int> test = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
foreach (int myInt in test.Reverse<int>())
{
if (myInt % 2 == 0)
{
test.Remove(myInt);
}
}
Using the ToArray() on a generic list allows you to do a Remove(item) on your generic List:
List<String> strings = new List<string>() { "a", "b", "c", "d" };
foreach (string s in strings.ToArray())
{
if (s == "b")
strings.Remove(s);
}
Select the elements you do want rather than trying to remove the elements you don't want. This is so much easier (and generally more efficient too) than removing elements.
var newSequence = (from el in list
where el.Something || el.AnotherThing < 0
select el);
I wanted to post this as a comment in response to the comment left by Michael Dillon below, but it's too long and probably useful to have in my answer anyway:
Personally, I'd never remove items one-by-one, if you do need removal, then call RemoveAll which takes a predicate and only rearranges the internal array once, whereas Remove does an Array.Copy operation for every element you remove. RemoveAll is vastly more efficient.
And when you're backwards iterating over a list, you already have the index of the element you want to remove, so it would be far more efficient to call RemoveAt, because Remove first does a traversal of the list to find the index of the element you're trying to remove, but you already know that index.
So all in all, I don't see any reason to ever call Remove in a for-loop. And ideally, if it is at all possible, use the above code to stream elements from the list as needed so no second data structure has to be created at all.
Using .ToList() will make a copy of your list, as explained in this question:
ToList()-- Does it Create a New List?
By using ToList(), you can remove from your original list, because you're actually iterating over a copy.
foreach (var item in listTracked.ToList()) {
if (DetermineIfRequiresRemoval(item)) {
listTracked.Remove(item)
}
}
If the function that determines which items to delete has no side effects and doesn't mutate the item (it's a pure function), a simple and efficient (linear time) solution is:
list.RemoveAll(condition);
If there are side effects, I'd use something like:
var toRemove = new HashSet<T>();
foreach(var item in items)
{
...
if(condition)
toRemove.Add(item);
}
items.RemoveAll(toRemove.Contains);
This is still linear time, assuming the hash is good. But it has an increased memory use due to the hashset.
Finally if your list is only an IList<T> instead of a List<T> I suggest my answer to How can I do this special foreach iterator?. This will have linear runtime given typical implementations of IList<T>, compared with quadratic runtime of many other answers.
As any remove is taken on a condition you can use
list.RemoveAll(item => item.Value == someValue);
List<T> TheList = new List<T>();
TheList.FindAll(element => element.Satisfies(Condition)).ForEach(element => TheList.Remove(element));
You can't use foreach, but you could iterate forwards and manage your loop index variable when you remove an item, like so:
for (int i = 0; i < elements.Count; i++)
{
if (<condition>)
{
// Decrement the loop counter to iterate this index again, since later elements will get moved down during the remove operation.
elements.RemoveAt(i--);
}
}
Note that in general all of these techniques rely on the behaviour of the collection being iterated. The technique shown here will work with the standard List(T). (It is quite possible to write your own collection class and iterator that does allow item removal during a foreach loop.)
For loops are a bad construct for this.
Using while
var numbers = new List<int>(Enumerable.Range(1, 3));
while (numbers.Count > 0)
{
numbers.RemoveAt(0);
}
But, if you absolutely must use for
var numbers = new List<int>(Enumerable.Range(1, 3));
for (; numbers.Count > 0;)
{
numbers.RemoveAt(0);
}
Or, this:
public static class Extensions
{
public static IList<T> Remove<T>(
this IList<T> numbers,
Func<T, bool> predicate)
{
numbers.ForEachBackwards(predicate, (n, index) => numbers.RemoveAt(index));
return numbers;
}
public static void ForEachBackwards<T>(
this IList<T> numbers,
Func<T, bool> predicate,
Action<T, int> action)
{
for (var i = numbers.Count - 1; i >= 0; i--)
{
if (predicate(numbers[i]))
{
action(numbers[i], i);
}
}
}
}
Usage:
var numbers = new List<int>(Enumerable.Range(1, 10)).Remove((n) => n > 5);
However, LINQ already has RemoveAll() to do this
var numbers = new List<int>(Enumerable.Range(1, 10));
numbers.RemoveAll((n) => n > 5);
Lastly, you are probably better off using LINQ's Where() to filter and create a new list instead of mutating the existing list. Immutability is usually good.
var numbers = new List<int>(Enumerable.Range(1, 10))
.Where((n) => n <= 5)
.ToList();
Using Remove or RemoveAt on a list while iterating over that list has intentionally been made difficult, because it is almost always the wrong thing to do. You might be able to get it working with some clever trick, but it would be extremely slow. Every time you call Remove it has to scan through the entire list to find the element you want to remove. Every time you call RemoveAt it has to move subsequent elements 1 position to the left. As such, any solution using Remove or RemoveAt, would require quadratic time, O(n²).
Use RemoveAll if you can. Otherwise, the following pattern will filter the list in-place in linear time, O(n).
// Create a list to be filtered
IList<int> elements = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
// Filter the list
int kept = 0;
for (int i = 0; i < elements.Count; i++) {
// Test whether this is an element that we want to keep.
if (elements[i] % 3 > 0) {
// Add it to the list of kept elements.
elements[kept] = elements[i];
kept++;
}
}
// Unfortunately IList has no Resize method. So instead we
// remove the last element of the list until: elements.Count == kept.
while (kept < elements.Count) elements.RemoveAt(elements.Count-1);
I would reassign the list from a LINQ query that filtered out the elements you didn't want to keep.
list = list.Where(item => ...).ToList();
Unless the list is very large there should be no significant performance problems in doing this.
The best way to remove items from a list while iterating over it is to use RemoveAll(). But the main concern written by people is that they have to do some complex things inside the loop and/or have complex compare cases.
The solution is to still use RemoveAll() but use this notation:
var list = new List<int>(Enumerable.Range(1, 10));
list.RemoveAll(item =>
{
// Do some complex operations here
// Or even some operations on the items
SomeFunction(item);
// In the end return true if the item is to be removed. False otherwise
return item > 5;
});
By assuming that predicate is a Boolean property of an element, that if it is true, then the element should be removed:
int i = 0;
while (i < list.Count())
{
if (list[i].predicate == true)
{
list.RemoveAt(i);
continue;
}
i++;
}
In C# one easy way is to mark the ones you wish to delete then create a new list to iterate over...
foreach(var item in list.ToList()){if(item.Delete) list.Remove(item);}
or even simpler use linq....
list.RemoveAll(p=>p.Delete);
but it is worth considering if other tasks or threads will have access to the same list at the same time you are busy removing, and maybe use a ConcurrentList instead.
I wish the "pattern" was something like this:
foreach( thing in thingpile )
{
if( /* condition#1 */ )
{
foreach.markfordeleting( thing );
}
elseif( /* condition#2 */ )
{
foreach.markforkeeping( thing );
}
}
foreachcompleted
{
// then the programmer's choices would be:
// delete everything that was marked for deleting
foreach.deletenow(thingpile);
// ...or... keep only things that were marked for keeping
foreach.keepnow(thingpile);
// ...or even... make a new list of the unmarked items
others = foreach.unmarked(thingpile);
}
This would align the code with the process that goes on in the programmer's brain.
foreach(var item in list.ToList())
{
if(item.Delete) list.Remove(item);
}
Simply create an entirely new list from the first one. I say "Easy" rather than "Right" as creating an entirely new list probably comes at a performance premium over the previous method (I haven't bothered with any benchmarking.) I generally prefer this pattern, it can also be useful in overcoming Linq-To-Entities limitations.
for(i = list.Count()-1;i>=0;i--)
{
item=list[i];
if (item.Delete) list.Remove(item);
}
This way cycles through the list backwards with a plain old For loop. Doing this forwards could be problematic if the size of the collection changes, but backwards should always be safe.
Just wanted to add my 2 cents to this in case this helps anyone, I had a similar problem but needed to remove multiple elements from an array list while it was being iterated over. the highest upvoted answer did it for me for the most part until I ran into errors and realized that the index was greater than the size of the array list in some instances because multiple elements were being removed but the index of the loop didn't keep track of that. I fixed this with a simple check:
ArrayList place_holder = new ArrayList();
place_holder.Add("1");
place_holder.Add("2");
place_holder.Add("3");
place_holder.Add("4");
for(int i = place_holder.Count-1; i>= 0; i--){
if(i>= place_holder.Count){
i = place_holder.Count-1;
}
// some method that removes multiple elements here
}
There is an option that hasn't been mentioned here.
If you don't mind adding a bit of code somewhere in your project, you can add and extension to List to return an instance of a class that does iterate through the list in reverse.
You would use it like this :
foreach (var elem in list.AsReverse())
{
//Do stuff with elem
//list.Remove(elem); //Delete it if you want
}
And here is what the extension looks like:
public static class ReverseListExtension
{
public static ReverseList<T> AsReverse<T>(this List<T> list) => new ReverseList<T>(list);
public class ReverseList<T> : IEnumerable
{
List<T> list;
public ReverseList(List<T> list){ this.list = list; }
public IEnumerator GetEnumerator()
{
for (int i = list.Count - 1; i >= 0; i--)
yield return list[i];
yield break;
}
}
}
This is basically list.Reverse() without the allocation.
Like some have mentioned you still get the drawback of deleting elements one by one, and if your list is massively long some of the options here are better. But I think there is a world where someone would want the simplicity of list.Reverse(), without the memory overhead.
Copy the list you are iterating. Then remove from the copy and interate the original. Going backwards is confusing and doesn't work well when looping in parallel.
var ids = new List<int> { 1, 2, 3, 4 };
var iterableIds = ids.ToList();
Parallel.ForEach(iterableIds, id =>
{
ids.Remove(id);
});
I would do like this
using System.IO;
using System;
using System.Collections.Generic;
class Author
{
public string Firstname;
public string Lastname;
public int no;
}
class Program
{
private static bool isEven(int i)
{
return ((i % 2) == 0);
}
static void Main()
{
var authorsList = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", no = 2 },
new Author{ Firstname = "Fred", Lastname = "Jones", no = 3 },
new Author{ Firstname = "Brian", Lastname = "Brains", no = 4 },
new Author{ Firstname = "Billy", Lastname = "TheKid", no = 1 }
};
authorsList.RemoveAll(item => isEven(item.no));
foreach(var auth in authorsList)
{
Console.WriteLine(auth.Firstname + " " + auth.Lastname);
}
}
}
OUTPUT
Fred Jones
Billy TheKid
I found myself in a similar situation where I had to remove every nth element in a given List<T>.
for (int i = 0, j = 0, n = 3; i < list.Count; i++)
{
if ((j + 1) % n == 0) //Check current iteration is at the nth interval
{
list.RemoveAt(i);
j++; //This extra addition is necessary. Without it j will wrap
//down to zero, which will throw off our index.
}
j++; //This will always advance the j counter
}
The cost of removing an item from the list is proportional to the number of items following the one to be removed. In the case where the first half of the items qualify for removal, any approach which is based upon removing items individually will end up having to perform about N*N/4 item-copy operations, which can get very expensive if the list is large.
A faster approach is to scan through the list to find the first item to be removed (if any), and then from that point forward copy each item which should be retained to the spot where it belongs. Once this is done, if R items should be retained, the first R items in the list will be those R items, and all of the items requiring deletion will be at the end. If those items are deleted in reverse order, the system won't end up having to copy any of them, so if the list had N items of which R items, including all of the first F, were retained,
it will be necessary to copy R-F items, and shrink the list by one item N-R times. All linear time.
My approach is that I first create a list of indices, which should get deleted. Afterwards I loop over the indices and remove the items from the initial list. This looks like this:
var messageList = ...;
// Restrict your list to certain criteria
var customMessageList = messageList.FindAll(m => m.UserId == someId);
if (customMessageList != null && customMessageList.Count > 0)
{
// Create list with positions in origin list
List<int> positionList = new List<int>();
foreach (var message in customMessageList)
{
var position = messageList.FindIndex(m => m.MessageId == message.MessageId);
if (position != -1)
positionList.Add(position);
}
// To be able to remove the items in the origin list, we do it backwards
// so that the order of indices stays the same
positionList = positionList.OrderByDescending(p => p).ToList();
foreach (var position in positionList)
{
messageList.RemoveAt(position);
}
}
Trace the elements to be removed with a property, and remove them all after process.
using System.Linq;
List<MyProperty> _Group = new List<MyProperty>();
// ... add elements
bool cond = false;
foreach (MyProperty currObj in _Group)
{
// here it is supposed that you decide the "remove conditions"...
cond = true; // set true or false...
if (cond)
{
// SET - element can be deleted
currObj.REMOVE_ME = true;
}
}
// RESET
_Group.RemoveAll(r => r.REMOVE_ME);
myList.RemoveAt(i--);
simples;

Most efficient way to prepend collection C#

I have a C# Array of objects that needs to stay in order that I'm trying to filter duplicates out of (not same object refference just same attribute values). The catch is the duplicate that has to go is the first one and the oldest needs to stay.
Current algorithm (semi pseudo code renamed everything) using IEnumerable
object[] filter(object[] array)
{
var set = new HashSet<Guid>();
var filtered = new List<object>();
for (int i = array.Length; i-- > 0;)
{
var item = array[i];
if (!set.Contains(item.ID))
{
set.Add(item.ID);
filtered = new List<object>(filtered.Prepend(item));
}
}
return filtered.ToArray();
}
I know it is currently O(n) but I am looking for a very efficient way of doing this. If possible with just arrays so I don't need to use .ToArray() and iterate again.
I could just make filtered an array of size array.length and put it in backwards i.e. "filtered[array.length-i] = item" but I don't want to have empty values.
Pushing to a stack can be thought of as adding to the start of a list, and popping from a stack can be thought of as removing an item from the start of a list.
Stack<T>.Push is a constant time operation as long as the stack has enough capacity, as the documentation says, so you can use a stack instead:
// using object[] doesn't make sense here as it doesn't have an ID property,
// so I have taken the liberty to create my interface
IHasID[] Filter(IHasID[] array)
{
var set = new HashSet<Guid>();
// if not many elements are expected to be filtered, giving the stack a initial capacity might be better
var filtered = new Stack<IHasID>(/*array.Length*/);
for (int i = array.Length; i-- > 0;)
{
var item = array[i];
if (set.Add(item.ID))
{
filtered.Push(item);
}
}
// ToArray creates an array in the pop order, O(n)
// https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.stack-1.toarray?view=net-5.0#remarks
return filtered.ToArray();
}
interface IHasID
{
Guid ID { get; }
}
Just use LINQ and it will be single O(n) CPU, O(n) RAM passthrough iterator without any further allocations:
var result = input.Reverse().DistinctBy(x=> x.YourKey);
Sample of implementation is here - LINQ's Distinct() on a particular property
You can also do same thing like this, cause all it does is just create group iterators:
var result = input.Reverse().GroupBy(x=> x.YourKey).Select(x=> x.First());

How to remove zero elements from List<string>?

Read couple of examples, but seems i`m doing something wrong.
Need to remove all "0" strings from a HUGE List without using hashtables.
Tryed using lambda samples from Stack Owerflow and MSDN examples, but looks i`m messing something up.
DataTable book = SQL.SqlGetTable(BookList.SelectedItem.ToString());
List<string> pagesExist = new List<string>();
for (int i = 0; i < book.Rows.Count; i++)
{
pagesExist.Add(book.Rows[i][0].ToString());
}
var found = pagesExist.Find(x => x == "0");
if (found != null)
pagesExist.Remove(found);
I have a pagesExist list of 4000 string elements.
Supposed that
var found = pagesExist.Find(x => x == "0");
will accumulate all zeroes in list and will remove them next string. But somehow found results in 0 elements
No need to create the pagesExist list. Just filter out all non zero rows using a simple linq query over the DataTable. This way your entire code is reduced to only:
DataTable book = SQL.SqlGetTable(BookList.SelectedItem.ToString());
var result = book.AsEnumerable().Where(r => r.Field<int>("FieldName") != 0);
I am assuming that the column contains integers only. If not then keep the use Field<string> and filter for != "0".
As a side note I would recommend looking into SqlGetTable. If it returns a DataTable it already brings all this data into memory from database, something that can be avoided with using linq directly over the DBMS using tools like linq-2-sql or linq-2-entities
You can use RemoveAll :
pagesExist.RemoveAll(p => p == "0");

Prevent infinite loop between objects referencing each other?

Okay, so I wasn't completely sure what headline would fit my problem, but here goes the description:
I have objects than can reference other objects, to create dropdown lists where the content/values is dependant on what values is chosen in "parent" dropdowns.
My dropdown objects contain an id, and a parentId (and other stuff, not relevant here).
I want to prevent the users from making infinite loops, like this:
List 1 (Dependant on list 3)
List 2 (Dependant on list 1)
List 3 (Dependant on list 2)
I've tried writing a recursive method to prevent it, but I cannot figure out the logic.
Could anyone tell me how you would ensure that an object isn't referencing it self "down the line" ? Or provide an example perhaps.
Any help is much appreciated.
The simplest way I can think of is to create a flattened list. Recursively iterate the objects and store each reference in a list. As you find new objects check each one in the list.
You'll either encounter an object referencing itself or run out of objects to search.
This method being suitable will depend on your requirements, speed / memory/ number of items in the list.
Since all object contain an id the list could store/check that instead if you need to check value equality instead of reference equality
If you have written a recursive function to manage those lists, one solution could be to create a list of elements and pass it as parameter into the recursive function and en each iteration add the current item to the list. To stop the recursive function, only check if the current item has been added previously to the list.
If you iterate through the actual elements of each list by relying on specific counters for each list you shouldn't find any problem. The most likely way to provoke an infinite loop is changing the value of a counter from an external source. Example:
for(int i = 0; i < max_i; i++)
{
if(val1[i] != null)
{
for(int j = 0; j < max_j; j++)
{
if(val2[j] != null)
{
//Delete or anything
//YOU CANNOT AFFECT NEITHER i NOR j DIRECTLY.
}
}
}
If you want to account for varying values of j in the internal part, you should rely on a different variable. Example:
if(val2[j] != null)
{
int j2 = j;
//Do whatever with j2, never with j
}
By doing this (associating different counters to different loops), no endless loop will occur. An endless loop occurs when: i = 1, 2, 3, 4 and suddenly i is changed to 2 by an "external source"; thus solution: NEVER change i other than through the for loop.
Thanks everyone for your input on this. I went with James suggestion using a list and ended up with the following code (which may or may not make sense for anyone else but me)
public static bool BadParent(int fieldId, int childId, List<int> list)
{
if (list == null)
list = new List<int>();
bool returnValue = true;
var field = EkstraFelterBLL.getEkstraFeltUdfraEkstraFeltId(fieldId);
if (field != null)
{
if (field.ParentEkstraFeltId == childId)
returnValue = false; //loop reference, fail
else if (list.Contains(field.EkstraFeltId))
returnValue = false; //already been in the cycle, fail
else
{
list.Add(field.EkstraFeltId);
returnValue = BadParent(field.ParentEkstraFeltId, childId, list);
}
}
return returnValue;
}

Don't understand why the ForEach command isn't working

I am wanting to trim any white space off a collection of strings. I used the following code but it doesn't seem to work. Could anyone explain why?
result.ForEach(f => f = f.Trim());
This won't work because you are assigning a new string reference to a local variable. This is probably what you are looking for:
result = result.Select(f => f.Trim()).ToList();
You are re-assigning the argument variable inside the scope of the lambda. It's a collapsed form of:
foreach(string value in myList)
{
Lambda(value);
}
void Lambda(string input)
{
input = input.Trim();
}
The simplest way would probably be to use a projection:
myList = myList.Select(str => str.Trim()).ToList();
foreach doesn't give you write access to the underlying collection, it only iterates through it, which means your change isn't stored back into the collection.
You can do two things:
Produce a new collection
var newResult = result.Select(f => f.Trim()).ToList();
Use a normal for-loop and change the original collection
for (int index = 0; index < result.Count; index++)
result[index] = result[index].Trim();

Categories

Resources