Home > OS >  How can I use foreach to look one variable ahead in the datatable with conditionals in C#?
How can I use foreach to look one variable ahead in the datatable with conditionals in C#?

Time:10-23

You guys helped me out a lot with my last question and now I have another.

I am new to C# and I have to iterate through a datatable to count transactions for different states. However, I have to remove duplicate transactions. I have something similar in javascript where I took one variable ahead in the table and if it matches the current variable then it will subtract one from the counter.

How could I do this in C#? Here is what I am trying to far but with no success:

if (row["State"].ToString().Contains("CA")) //Looks for CA state in the "state" column, however, it appears to not be finding it?
            {
                californiaTransactions2021  = 1;
               if(row["InvNum"].ToString() == row["InvNum"] 1.ToString())
                {
                    californiaTransactions2021 -= 1;
                }

Here is what my datatable looks like: Datatable

As you can see, some invoice numbers are the same for California and they must be subtracted for the counter. What is the correct syntax for C# to do this in the loop?

CodePudding user response:

If I needed to look ahead, and I needed to use foreach (rather than by index with for, which could use "index 1" to check the next row), then I would do something like this to preserve each row for one iteration and effectively trail my view of the current row by one cycle:

DataRow cachedRow = null;
foreach(var row in MyTable.Rows)
{
    if (cachedRow != null)
    {
        var currentRow = cachedRow;
        var nextRow = row; 
        
        // Do whatever you want with these two rows

    }
    cachedRow = row;
}
// Don't forget to also check the final row here

CodePudding user response:

You can make a custom enumeration:

static class Extensions
{
    public static IEnumerable<(T current, T? next)> WithNext<T>(this IEnumerable<T> enumerable)
    {
        using var enumerator = enumerable.GetEnumerator();
        if(!enumerator.MoveNext()) yield break;
        var current = enumerator.Current;

        // optional:
        //yield return (default, current);

        while (enumerator.MoveNext())
        {
            var next = enumerator.Current;
            yield return (current, next);
            current = next;
        }
        
        // optional:
        //yield return (current, default);
    }
}

Here is how it might be used:

    record Invoice
    {
        public int InvoiceNumber { get; set; }
        public DateTime Date { get; set; }
        public double Amount { get; set; }
        public string State { get; set; }
    }

    public void DoStuff()
    {
        var invoices = ReadInvoiceFile("Your/Path/Here.csv");
        var ca2021Invoices = invoices.Where(i => i.Date.Year == 2021 && i.State.Contains("CA"));
        foreach (var (thisInvoice, nextInvoice) in ca2021Invoices.WithNext())
        {
            //do your stuff comparing each invoice to the next
        }
    }


    private List<Invoice> ReadInvoiceFile(string path)
    {
        //realistically you would use a 3rd party library to do this
    }
  • Related