3

I've a LIST called invoice list that contains the following items.

ID:1
Total:5
Description:Test
Date:2012-01-01
Difference:

ID:2
Total:10
Description:Test
Date:2012-02-01
Difference:

ID:3
Total:15
Description:Test
Date:2012-03-01
Difference: 

ID:4
Total:20
Description:Test
Date:2012-04-01
Difference:

I need to calculate the difference between each invoices IDs using LINQ (preferably). The final output should look like below:

 ID:1
    Total:5
    Description:Test
    Date:2012-01-01
    Difference:0

    ID:2
    Total:10
    Description:Test
    Date:2012-02-01
    Difference:5

    ID:3
    Total:15
    Description:Test
    Date:2012-03-01
    Difference: 5

    ID:4
    Total:20
    Description:Test
    Date:2012-04-01
    Difference:5

Could some one please suggest what would be the best way to achieve above?

Steven
  • 166,672
  • 24
  • 332
  • 435
Nil Pun
  • 17,035
  • 39
  • 172
  • 294
  • What do you mean by "difference between each invoices"? Do you mean between ID=1 and ID=2, then ID=2 and ID=3? – Jon Skeet Aug 13 '12 at 07:24
  • 1
    Why must you do this with LINQ? Is this an exercise or homework? – Steven Aug 13 '12 at 07:36
  • possible duplicate of [Calculate difference from previous item with LINQ](http://stackoverflow.com/questions/3683105/calculate-difference-from-previous-item-with-linq) – Rawling Aug 13 '12 at 07:42

2 Answers2

8

I suspect Zip is your friend here:

var withNull = new Invoice[] { null }.Concat(invoices);

var withDifference = withNull.Zip(withNull.Skip(1),
                                  (x, y) => x == null ? y :
                                      new Invoice { 
                                          ID = y.ID,
                                          Total = y.Total,
                                          Date = y.Date,
                                          Difference = y.Total - x.Total
                                      }
                                  )
                             .ToList();

I'll leave working out how it works (and why you need the null) as an exercise - I can give some hints if necessary...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Only thing is items from index 1 onwards will be new whilst the first item will be a reference to the original, should you alway return `new Invoice` and have the null check inside the difference assignment, just to be consistent? – Bob Vale Aug 13 '12 at 07:55
2

as the source is a List you can use indexing to refer to the previous item, this can be achieved using the alternative form of select that uses a func based on both the item and its index.

var results=invoices.Select((x,i) => new Invoice { 
        Total = x.Total,
        Date = x.Date,
        Description=x.Description,
        Difference = x.Total - (i==0 ? 0 : invoices[i-1].Total)}
        );

You can use .ToList() on the end if you want the result as a list

Bob Vale
  • 18,094
  • 1
  • 42
  • 49