Share via


c# update all values in a integer list using linq

Question

Monday, December 1, 2014 2:30 PM

How to update a list of integer values using linq.

I have a list as below

 IList<int> list = new List<int>();

list.Add(1);

list.Add(2);

list.Add(3);

Now list contains values as {1,2,3}. Now i want to add value 6 to each items.

the result should be {7,8,9}. how to do it using linq?

All replies (7)

Monday, December 1, 2014 3:05 PM ✅Answered | 1 vote

It would be so?

static void Main (string [] args)
    {
      List <int> list = new List <int> ();
      list.Add (1);
      list.Add (2);
      list.Add (3);      

list = list.Select (x => x + 6) .ToList ();    

}


Monday, December 1, 2014 3:59 PM ✅Answered | 1 vote

If you change the type from IList<T> to List<T> you could use the ForEach extension method to iterate through it:

      List<int> list = new List<int>();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      list.ForEach(i =>
      {
        //....
      });

You won't be able to modify the int itself though. To do this, you should use a plain old for loop:

      List<int> list = new List<int>();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      for (int i = 0; i < list.Count; ++i) {
        list[i] = list[i] + 6;
      }

There is no reason to use LINQ just for the sake of it to do this.

Please remember to mark helpful posts as answer and/or helpful.


Monday, December 1, 2014 4:40 PM ✅Answered

There are so many reasons NOT to do this using LINQ.

First and foremost, it is not legal to modify the collection while you are iterating over it (querying it) with LINQ.

Consider this NON-WORKING scenario.

List<int> list = new List<int>() { 1, 2, 3 };
var query = list.Select( (val,index) => list[index] += 6 ).ToList(); // CAUSES EXCEPTION!
// InvalidOperationException
// Collection was modified; enumeration operation may not execute.

By modifying list with list[index] += 6, we alter the collection.  If this were an ordered collection, for example, this would alter the order we visit the items.

It's also not clear from your question what you want the result of the query to be.  integer values?  References to the original list items in the list (somehow?!?) or what?  If you want the result to be IEnumerable<int> then my original proposal is fine -- although it doesn't have the side effect of altering the values in the original list (and so it shouldn't!)

If you know that you are dealing with a List of integers, then traditional (non-LINQ) techniques will serve you better.

for( int i = 0; i < list.Count; ++i ) list[i] += 6;

On the other hand, if you are dealing with objects (not integers) then it's possible to use the proposed LINQ strategy because modifying the object does not modify the collection in which the object is contained.

class Foo
{
    public int val;
    public static implicit operator int( Foo foo )
    {
        return foo.val;
    }
    public static implicit operator Foo( int val )
    {
        return new Foo() { val = val };
    }
}
static void Main( string[] args )
{
    List<Foo> list = new List<Foo> { 1, 2, 3 };
    var query = list.Select( (val,index) => list[index].val += 6 );
    Console.WriteLine( string.Join( ",", query ) );
}

This modifies the object as a side effect of the selection, so be VERY careful to execute it only once.  Above we trust string.Join to evaluate the IEnumerable only once.  We also return the result of the increment (an int), so the query is an IEnuemrable<int>, and we've lost the ability to do further side effects downstream of this query.

But since we aren't necessarily concerned with the index at all, we can pass the object along as the result of the query and perform a side-effect during the selection again.

var query = list.Select( obj => { obj.val += 6; return obj } );

Please be very careful about lazy evaluation with Linq.  Consider the line above:  This doesn't execute until you actually use the query, as in .ToList() or something else that iterates over the IEnumerable.  All we have is an IEnumerable<Foo> that is ready to do its work, but nothing has started iterating over the enumerable yet.

Here's example #2 with the revised strategy of the list containing objects, and the query returning the object reference.

class Foo
{
    public int val;
    public static implicit operator int( Foo foo )
    {
        return foo.val;
    }
    public static implicit operator Foo( int val )
    {
        return new Foo() { val = val };
    }
    public override string ToString()
    {
        return val.ToString();
    }
}
static void Main( string[] args )
{
    List<Foo> list = new List<Foo> { 1, 2, 3 };
    var query = list.Select( obj => { obj.val += 6; return obj; } );
    Console.WriteLine( string.Join( ",", query ) );
}

(Incidentally, in the above example, Foo now needs a ToString override for the example to work correctly, but doesn't need the implicit "to int" operator)


Monday, December 1, 2014 2:54 PM | 1 vote

list.Select( n => n + 6 )


Monday, December 1, 2014 3:40 PM

So it means it will always create a new list with the update values. and source will still have same old values.

Is it not possible to do something in linq simliar like

list[0] +=6;

list[1] +=6;

list[2] +=6;

because. I am going to do this for more than 10000 values based on some criteria to all the values in the list. In that case it will create new 10000  values and update it. but still the source will remain same with the old values.


Monday, December 1, 2014 4:00 PM

See only assigns the result in the same list. The problem of this operation is scroll through the list and not the creation of a new list.


Monday, December 1, 2014 4:21 PM

one more way

var newList = from x in list
              select x + 6;