Search code examples
c#listsubtotal

Conditional Summation of Numerical Objects in a list


I have a dataset that I am outputting to a list in the following way:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

class Program
{
    static void Main(string[] args)
    {
        List<object> myList = new List<object>();

    int i = 1;
    using (StreamReader reader = new StreamReader("file.dat"))
    {
        string line;
        var locations = new Dictionary<string, int[]>() {
            {"210", new [] {405, 4, 128, 12, 141, 12, 247, 15, 121, 3}}, 
            {"310", new [] {321, 4, 112, 12, 125, 12, 230, 15, 105, 3}}, 
            {"410", new [] {477, 4, 112, 12, 125, 12, 360, 15, 105, 3}} 
        };

        while ((line = reader.ReadLine()) != null)
        {


            var lineStart = line.Substring(0, 3);

            if (lineStart == "210" || lineStart == "310" || lineStart == "410")
            {
                var currentLocations = locations[lineStart];
                var letters = line.Substring(currentLocations[0], currentLocations[1]);

                var tvolume =
                    int.Parse(line.Substring(currentLocations[2], currentLocations[3])) +
                    int.Parse(line.Substring(currentLocations[4], currentLocations[5]));

                var tprice = long.Parse(line.Substring(currentLocations[6], currentLocations[7]));
                var mvolume = tprice * tvolume * 0.01 * 0.0000001;
                var currency = line.Substring(currentLocations[8], currentLocations[9]);

                myList.Add(i);
                myList.Add(lineStart);
                myList.Add(letters);
                myList.Add(tvolume);
                myList.Add(tprice);
                myList.Add(mvolume);
                myList.Add(currency);

                // double total = myList.

                Console.WriteLine(i);
                Console.WriteLine(lineStart);
                Console.WriteLine(letters);
                Console.WriteLine(tvolume * 0.01);
                Console.WriteLine(tprice * 0.0000001);
                Console.WriteLine("{0:N}", mvolume);
                Console.WriteLine(currency + "\n");
                i = i + 1;
            }

        }
        int index = 0;
        Dictionary<string, int> tvolumeDictionary = new Dictionary<string, int>();
        Dictionary<string, long> mvolumeDictionary = new Dictionary<string, long>();
        string listLetters;

        foreach (object item in myList)
        {
            switch (index % 7)
            {
                case 2:
                    listLetters = item.ToString();
                    if (!tvolumeDictionary.Keys.Contains(listLetters))
                    {
                        tvolumeDictionary.Add(listLetters, 0);
                        mvolumeDictionary.Add(listLetters, 0);
                    }
                    break;
                case 3:
                    listLetters = myList[index - 1].ToString();
                    tvolumeDictionary[listLetters] = tvolumeDictionary[listLetters] + (int)item;
                    break;
                case 5:
                    listLetters = myList[index - 3].ToString();
                    mvolumeDictionary[listLetters] = mvolumeDictionary[listLetters] + long.Parse(item.ToString());
                    break;
            }
            index++;
        }

                //   Console.WriteLine(myList.Count);

        foreach (KeyValuePair<string, int> entry in tvolumeDictionary)
        {
            Console.WriteLine("{0} tvolume: {1} mVolume: {2}", entry.Key, entry.Value, mvolumeDictionary[entry.Key]);
        }

    }
}

}

File.dat, has thousands of lines to it, of which this will return several hundred. I wish to provide a breakdown of the numeric totals, for each "letters" (there are only about 4 categories in letters). AAAA, BBBB, CCCC and DDDD. If this was excel, i'd like it to do the subtotal function per change in letters column, but the catch here is that they are not in order.

The desired output is

 AAAA: TOTAL TVOLUME: TOTAL MVOLUME 
 BBBB: TOTAL TVOLUME: TOTAL MVOLUME
 CCCC: TOTAL TVOLUME: TOTAL MVOLUME
 DDDD: TOTAL TVOLUME: TOTAL MVOLUME

(above format not essential).


Solution

  • It seems you would like to have more flexibility when working with the extracted data, I strongly recommend using a custom class and Linq over a list with the custom class objects:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Linq;
    
    class Program
    {
        public class EntryLine
        {
            public int I { get; set; }
            public string LineStart { get; set; }
            public string Letters { get; set; }
            public int TVolume { get; set; }
            public long TPrice { get; set; }
            public double MVolume { get; set; }
            public string Currency { get; set; }
    
        }
    
        static void Main(string[] args)
        {
            List<EntryLine> myList = new List<EntryLine>();
            int i = 1;
            using (StreamReader reader = new StreamReader("file.dat"))
            {
                string line;
                var locations = new Dictionary<string, int[]>() {
                {"210", new [] {405, 4, 128, 12, 141, 12, 247, 15, 121, 3}}, 
                {"310", new [] {321, 4, 112, 12, 125, 12, 230, 15, 105, 3}}, 
                {"410", new [] {477, 4, 112, 12, 125, 12, 360, 15, 105, 3}} 
            };
    
                while ((line = reader.ReadLine()) != null)
                {
                    var lineStart = line.Substring(0, 3);
    
                    if (lineStart == "210" || lineStart == "310" || lineStart == "410")
                    {
                        var currentLocations = locations[lineStart];
                        var letters = line.Substring(currentLocations[0], currentLocations[1]);
    
                        var tvolume =
                            int.Parse(line.Substring(currentLocations[2], currentLocations[3])) +
                            int.Parse(line.Substring(currentLocations[4], currentLocations[5]));
    
                        var tprice = long.Parse(line.Substring(currentLocations[6], currentLocations[7]));
                        var mvolume = tprice * tvolume * 0.01 * 0.0000001;
                        var currency = line.Substring(currentLocations[8], currentLocations[9]);
    
                        myList.Add(new EntryLine()
                        {
                            I = i,
                            LineStart = lineStart,
                            Letters = letters,
                            TVolume = tvolume,
                            TPrice = tprice,
                            MVolume = mvolume,
                            Currency = currency
                        });
                        i = i + 1;
                    }
                }
    
                var x = myList.GroupBy(g => new { g.Letters, g.Currency })
                    .Select(a => new { a.Key.Letters, a.Key.Currency, TSum = a.Sum(s => s.TVolume), MSum = a.Sum(s => s.MVolume) });
    
                foreach (var item in x)
                {
                    Console.WriteLine("{0} currency: {1} tvolume: {2} mVolume: {3}", item.Letters, item.Currency, item.TSum, item.MSum);
                }
            }
        }
    }