ratty
ratty

Reputation: 13444

how do access previous item in list using linQ?

I have:

List<int> A  = new List<int>(){1,2,3,4,5,6};

List<int> m=new List<int>();
for(int i=1;i<A.count;i++)
{
int j=A[i]+A[i-1];
m.add(j);
}

how can I do this same operation using LinQ?

Upvotes: 21

Views: 41441

Answers (6)

Enigmativity
Enigmativity

Reputation: 117175

Another option is to implement your own Buffer operator and use that to make a simple LINQ statement.

public static IEnumerable<IEnumerable<T>> Buffer<T>(this IEnumerable<T> source, int size)
{
    var buffer = new List<T>();
    foreach (var t in source)
    {
        buffer.Add(t);
        if (buffer.Count() == size)
        {
            yield return buffer.AsEnumerable();
            buffer = buffer.Skip(1).ToList();
        }
    }
}

That allows this code:

List<int> B = A.Buffer(2).Select(x => x.Sum()).ToList();

Upvotes: 0

Hamiora
Hamiora

Reputation: 571

Ok so getting the next item in the list you can use:

A.SkipWhile(x => x != value).Skip(1).FirstOrDefault();

So to get the previous item use:

var B = A.ToList();
B.Reverse();
B.SkipWhile(x => x != value).Skip(1).FirstOrDefault();

Upvotes: 17

Luiz Felipe
Luiz Felipe

Reputation: 51

In case you only need the end value, you can Aggregate it, ie. you need previous value, but dont need each individual value to a new list.

int last = 0;
var r = m.Aggregate(last, (acc, it) => (last += it), (acc) => (last));

Upvotes: 1

Ani
Ani

Reputation: 113472

Well, a straightforward translation would be:

var m = Enumerable.Range(1, A.Count - 1)
                  .Select(i => A[i] + A[i - 1])
                  .ToList();

But also consider:

var m = A.Skip(1)
         .Zip(A, (curr, prev) => curr + prev)
         .ToList();

Or using Jon Skeet's extension here:

var m = A.SelectWithPrevious((prev, curr) => prev + curr)
         .ToList();

But as Jason Evans points out in a comment, this doesn't help all that much with readability or brevity, considering your existing code is perfectly understandable (and short) and you want to materialize all of the results into a list anyway.

There's nothing really wrong with:

var sumsOfConsecutives = new List<int>();

for(int i = 1; i < A.Count; i++)
   sumsOfConsecutives.Add(A[i] + A[i - 1]);

Upvotes: 58

Doctor Jones
Doctor Jones

Reputation: 21674

Some of the other answers assume that the elements of A are always going to be 1, 2, 3, 4, 5, 6. If those values ever change then the solution would break, such as the values changing to 2, 3, 6, 7, 10.

Here's my solution that will work with any values of A.

List<int> m = A.Skip(1).Select((element, index) => element + A.ElementAt(index)).ToList();

It is worth noting that sticking with a loop would probably be better than hacking together a Linq solution for this.

Upvotes: 4

Adriaan Stander
Adriaan Stander

Reputation: 166576

How about something like

var l = A.Skip(1).Select((x, index) => x + A[index]).ToList();

Upvotes: 4

Related Questions