|
Whoops! The parameter arg should have been called state .
That should be fixed now.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Knowing you are not quite perfect makes me feel a little more secure, but, in no way diminishes my respect for your technical excellence
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Alex Dunlop wrote: would it consume more memory due to the instantiation? Hi, I think to answer that clearly one would need to know the database, its internal format, etc., and the nature of your query that returns (I assume) some subset of rows. I don't have the expertise in this area to be more helpful.
But, yes, creating strings has a cost; here's an idea from uber-guru Jon Skeet you might try: [^]
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
This is my data on which a LINQ query executed. i have bit confusion about LINQ grouping used there. here is sample code.
List<Data> _data = new List<Data>
{
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B Securities",
Period = "2012 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2Q 2014A",
PeriodValue = "205.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2012 FYA",
PeriodValue = "101.33"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2Q 2014A",
PeriodValue = "201.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2012 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2Q 2014A",
PeriodValue = "201.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2012 FYA",
PeriodValue = "101.33"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2013 FYA",
PeriodValue = "222.30"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "1Q 2014A",
PeriodValue = "784.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2Q 2014A",
PeriodValue = "555.00"
},
};
var periods = _data.Select(y => y.Period).Distinct().OrderBy(y => y).ToArray();
var results =
_data
.GroupBy(
x => new { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName },
x => new { x.Period, x.PeriodValue })
.Select(x => new
{
x.Key,
Lookup = x.ToLookup(y => y.Period, y => y.PeriodValue),
})
.Select(x => new
{
x.Key.Section,
x.Key.Lineitem,
x.Key.BrokerCode,
x.Key.BrokerName,
Map = periods.ToDictionary(y => y, y => String.Join("|", x.Lookup[y])),
})
.ToArray();
var dt = new DataTable();
dt.Columns.Add("Section");
dt.Columns.Add("Lineitem");
dt.Columns.Add("BrokerCode");
dt.Columns.Add("BrokerName");
foreach (var period in periods)
{
dt.Columns.Add(period);
}
foreach (var result in results)
{
string[] key_values = new string[]
{
result.Section,
result.Lineitem,
result.BrokerCode,
result.BrokerName,
};
string[] period_values = periods.Select(p => result.Map[p]).ToArray()
dt.Rows.Add(key_values.Concat(period_values).ToArray());
}
i have to group on few fields and those are Section, LineItem, BrokerCode and Period but a guy does the grouping like this way
var results =
_data
.GroupBy(
x => new { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName },
x => new { x.Period, x.PeriodValue })
.Select(x => new
{
x.Key,
Lookup = x.ToLookup(y => y.Period, y => y.PeriodValue),
})
.Select(x => new
{
x.Key.Section,
x.Key.Lineitem,
x.Key.BrokerCode,
x.Key.BrokerName,
Map = periods.ToDictionary(y => y, y => String.Join("|", x.Lookup[y])),
})
.ToArray();
So my question is what kind of grouping is it.... see the below grouping code.
.GroupBy(
x => new { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName },
x => new { x.Period, x.PeriodValue })
Is it two set of grouping ? one set is { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName }
and another set is { x.Period, x.PeriodValue } ?
please guide me how the above grouping will be working ?
Thanks
|
|
|
|
|
|
Sir this kind of grouping still not clear.
GroupBy(
x => new { x.Section, x.Lineitem, x.BrokerCode, x.BrokerName },
x => new { x.Period, x.PeriodValue })
if it is one group then why there two x=> new{}
in first set they mention four fields name and in second set they mention two fields name.
still not clear the syntax how it is working. is it grouping on six fields ? if yes then developer could mention 6 fields name with in one
x=> new{x.Section, x.Lineitem, x.BrokerCode, x.BrokerName,x.Period, x.PeriodValue} ?
please help me to understand how these grouping is working. if possible please attach small sample code which explain how this grouping is working.
Thanks
|
|
|
|
|
Read the documentation again. The first parameter defines the object by which the list is grouped - the group's Key . The second parameter defines the type of objects within the group.
That GroupBy call will produce:
Group:
Key: { Section, Lineitem, BrokerCode, BrokerName }
Enumerable items:
{ Period, PeriodValue }
It is grouping on four fields, and projecting two fields for the items within each group.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Sir can you please provide me any good example which use the same kind of grouping. i search google but found not any similar LINQ grouping example code.
Thanks
|
|
|
|
|
Read the documentation!
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Stop trying to get other people to write your code for you, and start studying and experimenting.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
What is the meaning of forum....it is place where people discuss their problem and other give suggestion & answer if possible.
when a person do not know the answer or have negative mind or sluggish then those people come with excuse like this one.... "Stop trying to get other people to write your code for you, and start studying and experimenting."
Cheers.
|
|
|
|
|
It is for discussion, but what you're doing is NOT discussion. You keep saying "write more code for me."
|
|
|
|
|
Sorry sir if my approach was wrong. cheers!
|
|
|
|
|
i am not forcing anyone with gun to write down code for me. so anyone can overlook any post....am i right ?
cheers.
|
|
|
|
|
I like to know how to convert List<t> to Pivot datatable.
this is my sample data populated in List.
List<Data> _data = new List<Data>
{
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B Securities",
Period = "2012 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2Q 2014A",
PeriodValue = "205.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2012 FYA",
PeriodValue = "101.33"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Net Revenue",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2Q 2014A",
PeriodValue = "201.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2012 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2013 FYA",
PeriodValue = ""
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "1Q 2014A",
PeriodValue = "204.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "ZB",
BrokerName = "B. Riley Securities",
Period = "2Q 2014A",
PeriodValue = "201.00"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2012 FYA",
PeriodValue = "101.33"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2013 FYA",
PeriodValue = "222.30"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "1Q 2014A",
PeriodValue = "784.45"
},
new Data
{
Section = "Consensus Model",
Lineitem = "Cost of Goods Sold",
BrokerCode = "TU",
BrokerName = "Cantor Fitzgerald & Co",
Period = "2Q 2014A",
PeriodValue = "555.00"
},
};
Data grouping should be like Section, Lineitem, BrokerCode & Period
sample periods are like 2012 FYA or 2013 FYA...2Q 2014A
Desired output would be like below example
+-----------------+--------------------+-------------+-------------------+----------+----------+-----------+----------+
| Section | LineItem | Broker Code | Broker Name | 2012 FYA | 2013 FYA | 1Q 2014A | 2Q 2014A |
+-----------------+--------------------+-------------+-------------------+----------+----------+-----------+----------+
| Consensus Model | Net Revenue | ZB | B Securities | | | 204.45 | 205.00 |
| Consensus Model | Net Revenue | TU | Cantor Fitzgerald | 101.33 | | 204.45 | 201.00 |
| Consensus Model | Cost of Goods Sold | ZB | B Securities | | | 204.45 | 205.00 |
| Consensus Model | Cost of Goods Sold | TU | Cantor Fitzgerald | 101.33 | | 204.45 | 201.00 |
+-----------------+--------------------+-------------+-------------------+----------+----------+-----------+----------+
ToPivotTable() function sample code
public static DataTable ToPivotTable<T, TColumn, TRow, TData>(
this IEnumerable<T> source,
Func<T, TColumn> columnSelector,
Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector)
{
DataTable table = new DataTable();
var rowName = ((MemberExpression)rowSelector.Body).Member.Name;
table.Columns.Add(new DataColumn(rowName));
var columns = source.Select(columnSelector).Distinct();
foreach (var column in columns)
table.Columns.Add(new DataColumn(column.ToString()));
var rows = source.GroupBy(rowSelector.Compile())
.Select(rowGroup => new
{
Key = rowGroup.Key,
Values = columns.GroupJoin(
rowGroup,
c => c,
r => columnSelector(r),
(c, columnGroup) => dataSelector(columnGroup))
});
foreach (var row in rows)
{
var dataRow = table.NewRow();
var items = row.Values.Cast<object>().ToList();
items.Insert(0, row.Key);
dataRow.ItemArray = items.ToArray();
table.Rows.Add(dataRow);
}
return table;
}
Please guide me how to customize the code in the function ToPivotTable()
As a result i can use that function to get desired output.
if ToPivotTable() function code customization not possible then also tell me how to group data using LINQ to display data as i mention in the post.
Thanks
|
|
|
|
|
 That method only supports grouping on a single column. Dynamic grouping on multiple columns is not trivial.
This works for me given you sample input data:
public static DataTable ToPivotTable<T, TPivot>(
this IEnumerable<T> source,
IReadOnlyList<Expression<Func<T, object>>> groupColumns,
Func<T, string> pivotColumn, Func<T, TPivot> pivotValue)
{
var result = new DataTable();
var groupColumnMembers = groupColumns.Select(c => ((MemberExpression)c.Body).Member).Cast<PropertyInfo>().ToList();
foreach (var groupColumn in groupColumnMembers)
{
result.Columns.Add(new DataColumn(groupColumn.Name, groupColumn.PropertyType));
}
var p = Expression.Parameter(typeof(T), "p");
var tupleType = Type.GetType($"System.Tuple`{groupColumns.Count}");
var groupColumnTypes = groupColumnMembers.Select(x => x.PropertyType).ToArray();
var tupleConstructor = tupleType.MakeGenericType(groupColumnTypes).GetConstructor(groupColumnTypes);
var args = groupColumnMembers.Select(c => Expression.Property(p, c));
var body = Expression.New(tupleConstructor, args);
var groupByExpression = Expression.Lambda<Func<T, System.Runtime.CompilerServices.ITuple>>(body, p);
foreach (var group in source.GroupBy(groupByExpression.Compile()))
{
foreach (T element in group)
{
string pivotColumnName = pivotColumn(element);
if (!result.Columns.Contains(pivotColumnName))
{
result.Columns.Add(new DataColumn(pivotColumnName, typeof(TPivot)));
}
}
var row = result.NewRow();
for (int index = 0; index < group.Key.Length; index++)
{
row[index] = group.Key[index];
}
foreach (T element in group)
{
string pivotColumnName = pivotColumn(element);
TPivot pivotColumnValue = pivotValue(element);
row[pivotColumnName] = pivotColumnValue;
}
result.Rows.Add(row);
}
return result;
}
DataTable pivotedData = _data.ToPivotTable(
new List<Expression<Func<Data, object>>>
{
d => d.Section,
d => d.Lineitem,
d => d.BrokerCode,
d => d.BrokerName
},
d => d.Period,
d => d.PeriodValue); Output:
Section | Lineitem | BrokerCode | BrokerName | 2012 FYA | 2013 FYA | 1Q 2014A | 2Q 2014A
----------------------------------------------------------------------------------------------------------------------
Consensus Model | Net Revenue | ZB | B Securities | | null | null | null
Consensus Model | Net Revenue | ZB | B. Riley Securities | null | | 204.45 | 205.00
Consensus Model | Net Revenue | TU | Cantor Fitzgerald & Co | 101.33 | | 204.45 | 201.00
Consensus Model | Cost of Goods Sold | ZB | B. Riley Securities | | | 204.45 | 201.00
Consensus Model | Cost of Goods Sold | TU | Cantor Fitzgerald & Co | 101.33 | 222.30 | 784.45 | 555.00
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Wow !
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Sir thank you so much. i will test your code and let you know if i face any problem.
|
|
|
|
|
Sir i am using VS2013 and .net version 4.5.2.
so when i copy your code in your project then i am getting error for these below line which may work in .net upper version.
var tupleType = Type.GetType($"System.Tuple`{groupColumns.Count}");
var groupByExpression = Expression.Lambda<Func<T, System.Runtime.CompilerServices.ITuple>>(body, p);
foreach (var group in source.GroupBy(groupByExpression.Compile()))
{
}
sir can you please provide a code which may compile and work in .net version 4.5.2 using VS2013.
thank you.
|
|
|
|
|
ITuple was added in .NET 4.7.1; you will need to upgrade your project to at least that version to use it.
NB: .NET Framework 4.5.2 will reach end of support next April:
.NET Framework 4.5.2, 4.6, 4.6.1 will reach End of Support on April 26, 2022[^]
If you want a solution for an earlier version of .NET, then you'll need to write a specific method for your data - eg:
public static DataTable DataToPivotTable(this IEnumerable<Data> source)
{
var result = new DataTable();
result.Columns.Add(new DataColumn("Section", typeof(string)));
result.Columns.Add(new DataColumn("Lineitem", typeof(string)));
result.Columns.Add(new DataColumn("BrokerCode", typeof(string)));
result.Columns.Add(new DataColumn("BrokerName", typeof(string)));
var sourceList = source.ToList();
var periods = sourceList.Select(d => d.Period).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
foreach (string period in periods)
{
result.Columns.Add(new DataColumn(period, typeof(string)));
}
var groupedData = source.GroupBy(d => new
{
d.Section,
d.Lineitem,
d.BrokerCode,
d.BrokerName
});
foreach (var group in groupedData)
{
var row = result.NewRow();
row["Section"] = group.Key.Section;
row["Lineitem"] = group.Key.Lineitem;
row["BrokerCode"] = group.Key.BrokerCode;
row["BrokerName"] = group.Key.BrokerName;
foreach (var item in group)
{
row[item.Period] = item.PeriodValue;
}
result.Rows.Add(row);
}
return result;
}
DataTable pivotedData = _data.DataToPivotTable(); Output is identical to the previous method, but you won't be able to reuse this method for other input types or other sets of columns.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Sir, After reading your post i assume the code your provided can not be changed in such a way which can run in .net version 4.5.2
Thanks
|
|
|
|
|
The code in my first answer can't easily be changed to run in 4.5.2; you would need to provide your own class to represent the dynamic grouping.
The code in my reply should run in 4.5.2, but will only work for your specific Data class with the specific grouping from your question.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Sir the code you provided here is good but it is not flexible and as a result this can not be used in any scenario of pivot data re-presentation. your provided code is fixed and not dynamic.
can you please provide a extension method which convert any list to Pivot where i can supply those columns name on which grouping will be performed.
if possible please share anything similar code which really help me sir.
Thank you.
|
|
|
|
|
I have already provided you with such a code, but you rejected it because you've limited yourself to working in an obsolete version of the framework. A fact which you didn't mention until after I had given you the answer!
I've also given you a fixed version for your stated requirement that works in your chosen obsolete framework version.
And now you want me to spend even more time rewriting the dynamic version of the code to work in your chosen obsolete framework version, when you appear to have put precisely zero effort into solving your own problem?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
My intension is not give any problem to anyone. i could not do that to customize the function body which can take multiple fields for grouping and that why i posted that question here and i thought some one will help.
anyway thanks for your help sir. cheers.
|
|
|
|
|