locked
Linq GroupBy Arrays RRS feed

  • Question

  • Linq GroupBy seems to only work with anonymous arrays.  So new {a = x[0], b = x[1] , c = x[2]} will work but new object[] { x.Take(3)} does not work.  I'm using a DataTable so code below works.  I trying to get the groupby to be variable so I can group all the columns in the datatable except last column.  The results should return 4 rows from the datatable (not 6).

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    
    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("Headache", typeof(string));
                dt.Columns.Add("Nausea", typeof(string));
                dt.Columns.Add("Temp", typeof(string));
                dt.Columns.Add("Flu", typeof(string));
    
                dt.Rows.Add(new string[] {"no", "no" ,"normal", "no"});
                dt.Rows.Add(new string[] {"yes", "no" ,"high", "yes"});
                dt.Rows.Add(new string[] {"yes", "yes" ,"high", "yes"});
                dt.Rows.Add(new string[] {"yes", "no" ,"normal", "no"});
                dt.Rows.Add(new string[] {"no", "no" ,"high", "no"});
                dt.Rows.Add(new string[] {"no", "no" ,"high", "yes"});
    
                var dict = dt.AsEnumerable()
                    .GroupBy(x => new { Headache = x.Field<string>("Headache"), Nausea = x.Field<string>("Nausea"), Temp = x.Field<string>("Temp") }, y => y)
                    .ToDictionary(x => x.Key, y => y.ToList());
    
                DataTable dt2 = dict.Where(x => x.Value.Count == 1).SelectMany(y => y.Value).CopyToDataTable();
    
                //or simply this
                DataTable dt3 = dt.AsEnumerable()
                    .GroupBy(x => new { Headache = x.Field<string>("Headache"), Nausea = x.Field<string>("Nausea"), Temp = x.Field<string>("Temp") })
                    .Where(x => x.Count() == 1).SelectMany(y => y).CopyToDataTable();
    
            }
        }
    }
    ​


    jdweng


    Monday, October 19, 2015 11:03 PM

All replies

  • Hello,

    This is not the same but thought it might be worth looking at

    using System.Collections.Generic;
    
    namespace GroupDataTableDups
    {
        internal class Results
        {
            public int Line { get; set; }
    
            public string Name { get; set; }
    
            public int Count { get; set; }
    
            public List<System.Data.DataRow> Rows { get; set; }
        }
    }

    .

    using System;
    using System.Data;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace GroupDataTableDups
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add(new DataColumn
                {
                    ColumnName = "ID",
                    DataType = typeof(int),
                    AutoIncrement = true,
                    ColumnMapping = MappingType.Hidden
                });
    
                dt.Columns.Add("Line", typeof(int));
                dt.Columns.Add("Name", typeof(string));
    
                dt.Rows.Add(new object[] { null, 0, "Ras1" });
                dt.Rows.Add(new object[] { null, 0, "Ras1" });
                dt.Rows.Add(new object[] { null, 0, "Ras" });
                dt.Rows.Add(new object[] { null, 0, "Ras2" });
                dt.Rows.Add(new object[] { null, 0, "Ras2" });
                dt.Rows.Add(new object[] { null, 1, "Ras" });
                dt.Rows.Add(new object[] { null, 0, "Ras" });
                dt.Rows.Add(new object[] { null, 0, "Ras" });
    
                var query = dt.AsEnumerable()
                    .OrderBy(
                        (row) => row.Field<string>("Name"))
                    .GroupBy((row) => new
                    {
                        Line = row.Field<int>("Line"),
                        Name = row.Field<string>("Name")
                    })
                    .Take(3)
                    .Select((group) => new Results
                    {
                        Line = group.Key.Line,
                        Name = group.Key.Name,
                        Count = group.Count(),
                        Rows = group.AsEnumerable().ToList()
                    }).ToList();
    
                foreach (var topItem in query)
                {
                    Console.WriteLine("{0} {1}", topItem.Line, topItem.Name);
                    foreach (var item in topItem.Rows)
                    {
                        Console.WriteLine("    {0} {1} {2}",
                            item.Field<int>("ID"),
                            item.Field<int>("Line"),
                            item.Field<string>("Name"));
                    }
                }
            }
        }
    }


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my webpage under my profile but do not reply to forum questions.
    Microsoft Developer tools
    Developer’s Guide to Windows 10 video series

    Tuesday, October 20, 2015 2:09 AM
  • Your code uses anonymous groupby which works.  I need the equivalent to below which doesn't work.

    .GroupBy(x => new object[] { x.ItemArray.Take(x.ItemArray.Count() - 1).ToArray()})


    jdweng

    Tuesday, October 20, 2015 9:23 AM
  • What I have found is your GroupBy on ItemArray with Take will (as you have already learned) will not work if not using anonymous types in both GroupBy and Select which is why I looked at an alternate and as indicated was not what you wanted but might provide other ideas.

    I only use an anonymous type for the GroupBy and a class for the Select after validating what you tried indeed did not work as one might think it would.



    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my webpage under my profile but do not reply to forum questions.
    Microsoft Developer tools
    Developer’s Guide to Windows 10 video series

    Tuesday, October 20, 2015 9:38 AM