HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Identical linq for different index

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
linqidenticaldifferentforindex

Problem

I am parsing excel data and need to create object based on StartDate-EndDate difference.

Is there a better way to have only one linq perform this task and return two different result sets ? Only difference in both linq is just the variable on which its applied.

```
private Dictionary>>[] ParseData(ExcelFile file, Dictionary[] ConfigMap)
{

// Extract the information from the excel file
var excelData = file.GetWorksheetData(sheet: 0, rowStart: 2);

var monthlyRows = excelData.Rows.Where(r => (DateTime.FromOADate((double)r[EndDateCol]) - DateTime.FromOADate((double)r[StartDateCol])).Days > 1);
var dailyRows = excelData.Rows.Where(r => (DateTime.FromOADate((double)r[EndDateCol]) - DateTime.FromOADate((double)r[StartDateCol])).Days == 1);

var monthlyData = monthlyRows.Where(r => r[KeyCol] != null && ConfigMap[0].ContainsKey((string)r[KeyCol]))
.GroupBy(r => (string)r[KeyCol])
.ToDictionary(g => g.Key,
g => g.GroupBy(r => DateTime.FromOADate((double)r[DateCol]))
.ToDictionary(c => c.Key,
c => c.Select(r => new DataPoint(DateTime.FromOADate((double)r[StartDateCol]), new Decimal((double)r[PriceCol])))
.ToList()));

var dailyData = dailyRows.Where(r => r[KeyCol] != null && ConfigMap[1].ContainsKey((string)r[KeyCol]))
.GroupBy(r => (string)r[KeyCol])
.ToDictionary(g => g.Key,
g => g.GroupBy(r => DateTime.FromOADate((double)r[DateCol]))
.ToDictionary(c => c.Key,
c => c.Select(r => new DataPoint(DateTime.

Solution

Assuming monthlyRows and dailyRows are both IEnumerable, a first step could be to extract a method (assuming return type here, I only skimmed through your code):

private Dictionary> GetDataDictionary(IEnumerable data)
{
    var result = data.Where(r => r[KeyCol] != null && ConfigMap[0].ContainsKey((string)r[KeyCol]))
                                   .GroupBy(r => (string)r[KeyCol])
                                   .ToDictionary(g => g.Key,
                                                 g => g.GroupBy(r => DateTime.FromOADate((double)r[DateCol]))
                                                       .ToDictionary(c => c.Key,
                                                                     c => c.Select(r => new DataPoint(DateTime.FromOADate((double)r[StartDateCol]), new Decimal((double)r[PriceCol])))
                                                                           .ToList()));    
    return result;
}


Your ParseData method's body could then look like this:

// Extract the information from the excel file
    var excelData = file.GetWorksheetData(sheet: 0, rowStart: 2);

    var monthlyRows = excelData.Rows.Where(r => (DateTime.FromOADate((double)r[EndDateCol]) - DateTime.FromOADate((double)r[StartDateCol])).Days > 1);
    var monthlyData = GetDataDictionary(monthlyRows);

    var dailyRows = excelData.Rows.Where(r => (DateTime.FromOADate((double)r[EndDateCol]) - DateTime.FromOADate((double)r[StartDateCol])).Days == 1);
    var dailyData = GetDataDictionary(dailyRows);

    return new Dictionary>>[] { monthlyData, dailyData };


That solves one issue.

Next step would be to break down the LINQ query and make the code self-explanatory as far as why you need to have a dictionary of dictionaries of lists.. and then make that simpler.

Code Snippets

private Dictionary<DateTime, List<DataPoint>> GetDataDictionary(IEnumerable<ExcelDataRow> data)
{
    var result = data.Where(r => r[KeyCol] != null && ConfigMap[0].ContainsKey((string)r[KeyCol]))
                                   .GroupBy(r => (string)r[KeyCol])
                                   .ToDictionary(g => g.Key,
                                                 g => g.GroupBy(r => DateTime.FromOADate((double)r[DateCol]))
                                                       .ToDictionary(c => c.Key,
                                                                     c => c.Select(r => new DataPoint(DateTime.FromOADate((double)r[StartDateCol]), new Decimal((double)r[PriceCol])))
                                                                           .ToList()));    
    return result;
}
// Extract the information from the excel file
    var excelData = file.GetWorksheetData(sheet: 0, rowStart: 2);

    var monthlyRows = excelData.Rows.Where(r => (DateTime.FromOADate((double)r[EndDateCol]) - DateTime.FromOADate((double)r[StartDateCol])).Days > 1);
    var monthlyData = GetDataDictionary(monthlyRows);

    var dailyRows = excelData.Rows.Where(r => (DateTime.FromOADate((double)r[EndDateCol]) - DateTime.FromOADate((double)r[StartDateCol])).Days == 1);
    var dailyData = GetDataDictionary(dailyRows);

    return new Dictionary<string, Dictionary<DateTime, List<DataPoint>>>[] { monthlyData, dailyData };

Context

StackExchange Code Review Q#44811, answer score: 6

Revisions (0)

No revisions yet.