Question

Link to csv file

I have the following code that filters through a csv file and stores the 1st and 5th column in one list (values) and the 7th and 11th columns in another list (values1).

The aim is to search through each element in the first list (values) and then check every element in the second list (value1) for matching periods before adding all matching cases' payouts and then comparing to the first list's payout with a 1% error margin.

The following code takes care of the searching through each list part with the two foreach loops below. But I am having problems defining a variable (i.e. the var temp does not work and gives me an error of FormatException: Input string was not in a correct format." error when I run the code) to store or add the Payouts together in the event that there are multiple occurrences of a period in the second list.

Also is it possible to define the type of the variable Payout and Period when I define the lists? The problem lies with the fact that they are anonymous variables as supposed to defined ones.

Any help is appreciated, thanks.

var values = File.ReadLines(path).Skip(1)
      .Select(x => x.Split(','))
      .Where(x => x[0] != string.Empty)
      .Select(x => new { Period = int.Parse(x[0]), Payout = decimal.Parse(x[4]) })
      .ToList();

values = values.OrderBy(x => x.Period)
.ToList();

var values1 = File.ReadLines(path).Skip(1)
      .Select(x => x.Split(','))
      .Where(x => x[0] == string.Empty)
      .Select(x => new { Period = int.Parse(x[6]), Payout = decimal.Parse(x[10]) })
      .ToList();
//Console.WriteLine(values1);

values1 = values1.OrderBy(x => x.Period)
.ToList();
//Console.WriteLine(values1[0]);

decimal temp = 0;

foreach (var value in values)
{
    foreach (var value1 in values1)
    {
        if (value.Period == value1.Period)
        {
            temp += value1.Payout;
        }
    }
}
Was it helpful?

Solution

FormatException means some of your data is not what you expect.

You can use something like the following to check for invalid data.

   int dummyPeriod ;
   decimal dummyPayout;

   var badValues = File.ReadLines(path).Skip(1)
     .Select(x => x.Split(','))
     .Where(x => !Int32.TryParse(x[0], out dummyPeriod) || 
              !Decimal.TryParse(x[4], out dummyPayout))

     .Select(x => new { Period =  x[0] , Payout = x[4]   })
     .ToList();

If you want to just ignore these lines you can invert the selection, eg

var values = File.ReadLines(path).Skip(1)
  .Select(x => x.Split(','))
  .Where(x => Int32.TryParse(x[0], out dummyPeriod) && 
              Decimal.TryParse(x[4], out dummyPayout))    
  .Select(x => new { Period = int.Parse(x[0]), Payout = decimal.Parse(x[4]) })
  .ToList();

Note that

 decimal.parse(x[4]) 

will fail if x[4] is an empty string, whereas you may want to interpret this as zero.

OTHER TIPS

From the line: .Select(x => new { Period = int.Parse(x[0]), Payout = decimal.Parse(x[4]) })

This is failing because you are attempting to convert an invalid string to an integer or decimal. All of the following will fail:

int.Parse("20.5")
int.Parse("20z")
decimal.Parse("20.5.5")
decimal.Parse("20.0m")

Double-check your input, most likely the data you're reading in is not what you expect it to be. That is x[0] and/or x[4] are not valid text to be converted to their respective number types. Add a breakpoint or extract that behaviour so you can debug/test it to validate your text input.

Perhaps your column indexes are off, or perhaps a row in your CSV file is not formatted correctly.

take the double loop out, do the join on period and aggregate payout.

try this:

class Program
{
    static void Main()
    {
        List<Dur> fList = new List<Dur>();
        fList.Add(new Dur(10));
        fList.Add(new Dur(11));
        fList.Add(new Dur(12));
        fList.Add(new Dur(13));

        List<Sec> sList = new List<Sec>();
        sList.Add(new Sec(20));
        sList.Add(new Sec(22));
        sList.Add(new Sec(11));
        sList.Add(new Sec(10));
        sList.Add(new Sec(25));
        var result = from x in fList
                  join y in sList on x._x equals y._y
                  select x._x;
        var sum = result.Sum();
        Console.Write(sum);
        Console.ReadKey();

    }
}

class Dur
{
    public Dur(int x)
    {
        _x = x;
    }
    public int _x;
}

class Sec
{
    public Sec(int y)
    {
        _y = y;
    }
    public int _y;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top