I have Rows object that is IEnumerable<dynamic>, it has 5 properties (columns) and 100 rows. One of the properties/columns is Group, only 2 distinct groups out of 100 rows, so first I run a distinct against it:
IEnumerable<dynamic> Groups = Rows.Select(x => x.Group).Distinct();
This works, no error.
Then I want to go back to my Rows object and loop through them where this group = the group in Rows, like this:
foreach (string Group in Groups)
{
IEnumerable<dynamic> GroupData =
from rowdata in Rows
where rowdata.Group = #Group
select rowdata;
But I get this error on the last line:
'WebMatrix.Data.DynamicRecord' does not contain a definition for 'Group'
Anyone knows why this isn't working?
Surely I can do this another way, but I wanted to use c# select statement instead. How can I though?
Edit to show usage:
foreach (var row in GroupData){
string ThisGroup = row.Group
}
...
Instead of selecting twice, group on the Group value:
IEnumerable<IGrouping<string, dynamic>> groups = Rows.GroupBy(x => (string)x.Group);
Now you can just loop through the result:
foreach (IGrouping<string, dynamic> group in groups) {
...
}
The IGrouping<> object has a Key property which is the value that you grouped on, and it's also a collection of the values in the group.
Related
I have a linq statement like following,
var v1 = from s in context.INFOONEs group s by s.DATET into xyz select xyz;
I am trying like following to display the results
foreach (var x in v1)
{
Console.WriteLine(x.);
}
But intellisence is not showing the columns when I type x.
What I am doing wrong? And what is the right way to achieve what I am trying to accomplish?
Thanks
because there is no column in x. There are some record(s) under each group.So you need to get those records:
foreach (var x in v1)
{
Console.WriteLine(x.Key); // display the Key of current group
foreach(var item in x) // iterate over the records in the group
{
Console.WriteLine(item.) // here you can access your columns
}
}
//SELECT table1.GG_ITEM, Sum(table1.REM_QTY) AS SumPerGG_ITEM
//FROM table1
//WHERE (table1.SUGG_DOCK_DATE Is Not Null)
//GROUP BY table1.GG_ITEM
//ORDER BY table1.GG_ITEM;
var try1 = (from row in db2.Dumps select new { Type1 = row.GA_ITEM, Type2 = row.REM_QTY });
Debug.Print(":::::try1:::::");
foreach (var row in try1)
{
Debug.Print(row.Type1.ToString());
Debug.Print(row.Type2.ToString());
}
var try2 = (from row in db2.Dumps group row by row.GA_ITEM into g select new { Type1 = g.Key, Type2 = g.ToList() });
Debug.Print("::::try2:::::");
foreach (var row in try2)
{
Debug.Print(row.Type1.ToString());
Debug.Print(row.Type2.ToString());
}
I'm converting an Access SQL query to Linq. The two columns I am selecting from my table Dumps are GA_ITEM and REM_QTY. My try1 is working out just fine and I see the contents of both columns printed out. My try1 is not yet duplicating the functionality of the Access SQL query.
My try2 is an attempt at grouping. For my try2 row.Type1.ToString() is readable however row.Type2.ToString() is showing up in the output window as:
System.Collections.Generic.List`1[garminaspsandbox3.Models.Dump]
What I really would like to do is in try2 select GA_ITEM and REM_QTY like I did in try1 and group by GA_ITEM however those fields aren't showing up in my autocomplete for the g object.
Does anyone know how to do this in Linq?
Thank you for posting...
Your Type2 property holds a List, not a single item,So you need to use another loop and iterate over the items in that group:
foreach (var row in try2)
{
Debug.Print(row.Type1.ToString());
foreach(var item in row.Type2)
{
Debug.Print(item.GA_ITEM);
Debug.Print(item.REM_QTY);
}
}
I Have DataTable Similar Like this.
If the adults value and child value are same. I need to Remove it and count that. I need a output similar like this.
Can anyone please help me on this???.
Thank you,
You want to group by adults+child:
var groups = tblRoooms.AsEnumerable()
.GroupBy(r => new{ Adults = r.Field<int>("Adults"), Child = r.Field<int>("Child") });
var tblRooomsCopy = tblRoooms.Clone(); // creates an empty clone of the table
foreach(var grp in groups)
{
int roomCount = grp.Sum(r => r.Field<int>("Roomcount"));
DataRow row = tblRooomsCopy.Rows.Add();
row.SetField("RoomNo", grp.First().Field<int>("RoomNo"));
row.SetField("Roomcount", roomCount);
row.SetField("Adults", grp.Key.Adults);
row.SetField("Child", grp.Key.Child);
}
Now you have your desired result in tblRooomsCopy.
I won't write the complete code for you but I will describe a suggested way: first order the datatable by adults and child, that will cause same rows to be consecutive, create a list that you will fill rows to be deleted
then use foreach to compare each row with the previous one, if it has the same value then add it to the list of rows to be removed, finally you will delete the rows in the list
Given the following code:
var filtered = (from a in lijst select a);
foreach (string brandstof in checkedListBoxHoofdbrandstof.CheckedItems)
{
MessageBox.Show(brandstof);
filtered = (from a in lijst where a.Hoofdbrandstof.Contains(brandstof) select a);
}
MessageBox.Show(filtered.Count().ToString());
lijst is a List of a class , with about 16000 items
When checkedListBoxHoofdbrandstof.CheckedItems contains more than 1 item, the query only uses the results from the last where-clause.
For example: I have 2 values, A and B, and despite the fact that A returns 100 rows, and B returns 50 rows, only the last 50 rows are included as a result. A is not included in the results anymore.
I tried using a.Hoofdbrandstof.Any, but that results in an error about types. I also tried a.Hoofdbrandstof.Equals, with the same results.
Does anyone know how I can combine these results, so that both the results from A and B are in var filtered?
The simple way:
var checkedItems = checkedListBoxHoofdbrandstof.CheckedItems;
var filtered = from a in lijst
where checkedItems.Contains(a.Hoofdbrandstof)
select a
But complexity of this method if O(n^2) to reduce it to O(n) use a Join operation
var checkedItems = checkedListBoxHoofdbrandstof.CheckedItems.Cast<string>().ToList();
var filtered = from a in lijst
join checkedItem in checkedItems on a.Hoofdbrandstof equals checkedItem
select a
I have a known list of strings like the following:
List<string> groupNames = new List<string>(){"Group1","Group2","Group3"};
I also have a list of strings that is not known in advance that will be something like this:
List<string> dataList = new List<string>()
{
"Group1.SomeOtherText",
"Group1.SomeOtherText2",
"Group3.MoreText",
"Group2.EvenMoreText"
};
I want to do a LINQ statement that will take the dataList and convert it into either an anonymous object or a dictionary that has a Key of the group name and a Value that contains a list of the strings in that group. With the intention of looping over the groups and inner looping over the group list and doing different actions on the strings based on which group it is in.
I would like a data structure that looks something like this:
var grouped = new
{
new
{
Key="Group1",
DataList=new List<string>()
{
"Group1.SomeOtherText",
"Group1.SomeOtherText2"
}
},
new
{
Key="Group2",
DataList=new List<string>()
{
"Group2.EvenMoreText"
}
}
...
};
I know I can just loop through the dataList and then check if each string contains the group name then add them to individual lists, but I am trying to learn the LINQ way of doing such a task.
Thanks in advance.
EDIT:
Just had another idea... What if my group names were in an Enum?
public enum Groups
{
Group1,
Group2,
Group3
}
How would I get that into a Dictionary>?
This is what I am trying but i am not sure how to form the ToDictionary part
Dictionary<Groups,List<string>> groupedDictionary = (from groupName in Enum.GetNames(typeof(Groups))
from data in dataList
where data.Contains(groupName)
group data by groupName).ToDictionary<Groups,List<string>>(...NOT SURE WHAT TO PUT HERE....);
EDIT 2:
Found the solution to the Enum question:
var enumType = typeof(Groups);
Dictionary<Groups,List<string>> query = (from groupName in Enum.GetValues(enumType).Cast<Groups>()
from data in dataList
where data.Contains(Enum.GetName(enumType, groupName))
group data by groupName).ToDictionary(x => x.Key, x=> x.ToList());
That looks like:
var query = from groupName in groupNames
from data in dataList
where data.StartsWith(groupName)
group data by groupName;
Note that this isn't a join, as potentially there are overlapping group names "G" and "Gr" for example, so an item could match multiple group names. If you could extract a group name from each item (e.g. by taking everything before the first dot) then you could use "join ... into" to get a group join. Anyway...
Then:
foreach (var result in query)
{
Console.WriteLine("Key: {0}", result.Key);
foreach (var item in result)
{
Console.WriteLine(" " + item);
}
}
If you really need the anonymous type, you can do...
var query = from groupName in groupNames
from data in dataList
where data.StartsWith(groupName)
group data by groupName into g
select new { g.Key, DataList = g.ToList() };