kk1076
kk1076

Reputation: 1748

Combine list values based on column C#

I am trying to bind two list values into a single list based on the values of the column.

below is the list am getting it.

TestCaseName Screen   IEStatus     IEPath      FFStatus   FFPath       GCStatus      GCPath
--------------------------------------------------------------------------------------------
TC001        Yes        Pass       C:\\a.jpg     null         null        null         null
TC002        Yes        Pass       C:\\b.jpg     null         null        null         null
TC001        Yes        null         null        Pass     C:\\c.jpg       null         null
TC002        Yes        null         null        Pass     C:\\d.jpg       null         null

But I want to combine the values and display as below

TestCaseName Screen   IEStatus     IEPath      FFStatus   FFPath       GCStatus      GCPath
--------------------------------------------------------------------------------------------
TC001        Yes        Pass       C:\\a.jpg     Pass     C:\\c.jpg        null       null
TC002        Yes        Pass       C:\\b.jpg     Pass     C:\\d.jpg        null       null

Below is my code

     List<ResultProperties> lstCommon = new List<ResultProperties>();
     List<ResultProperties> lstNew= new List<ResultProperties>();
     var checked_boxes = this.Controls.OfType<CheckBox>().Where(c => c.Checked);
     foreach (CheckBox cbx in checked_boxes)
     {
        Program obj = new Program();             
        lstNew =  obj.PerformTest(cbx.Text, textBox1.Text);                           
        foreach (ResultProperties item in lstNew)
        {
           lstCommon.Add(item);
        }
     }

Any suggestions will be greatly helpful..

Upvotes: 1

Views: 87

Answers (2)

Nicholas Carey
Nicholas Carey

Reputation: 74317

Rather than doing it in a single Linq expression, I would probably do something list this, so as to avoid multiple iterations over the source data:

List<ResultProperties> a = LoadSourceList() ;

IEnumerable<IGrouping<string,ResultProperties> groups =
  a
  .GroupBy( x => x.TestCaseName , StringComparer.OrdinalIgnoreCase )
  ;

List<ResultProperties> coalesced = new List<ResultProperties>() ;

foreach( IGrouping<string,ResultProperties> group in groups )
{
  ResultProperties item = null ;

  foreach( ResultProperty rp in group )
  {
    item          = item          ?? rp          ;
    item.Screen   = item.Screen   ?? rp.Screen   ;
    item.IEStatus = item.IEStatus ?? rp.IEStatus ;
    item.IEPath   = item.IEPath   ?? rp.IEPath   ;
    item.FFStatus = item.FFStatus ?? rp.FFStatus ;
    item.FFPath   = item.FFPath   ?? rp.FFPath   ;
    item.GCStatus = item.GCStatus ?? rp.GCStatus ;
    item.GCPath   = item.GCPath   ?? rp.GCPath   ;
  }

  coalesced.Add(item) ;

}

At the end of the day, the source list is unchanged and coalesced should contain a single ResultProperties for each distinct test case name, with all the value coalesce on a first-wins strategy (the first non-null value for a property defines the property for the group).

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726849

You should be able to do this with GroupBy, like this:

var res = testData
    .GroupBy(test => test.TestCaseName)
    .Select(g => new ResultProperties {
        TestCaseName = g.Key
    ,   Screen = g.Select(test => test.Screen).FirstOrDefault()
    ,   IEStatus = g.Select(test => test.IEStatus).FirstOrDefault()
    ,   IEPath = g.Select(test => test.IEPath).FirstOrDefault()
    ,   FFStatus = g.Select(test => test.FFStatus).FirstOrDefault()
    ,   FFPath = g.Select(test => test.FFPath).FirstOrDefault()
    ,   GCStatus = g.Select(test => test.GCStatus).FirstOrDefault()
    ,   GCPath = g.Select(test => test.GCPath).FirstOrDefault()
    }).ToList();

The idea is to form groups based on the name of the test, and then grab the first non-null entry for each attribute in the group.

Upvotes: 1

Related Questions