user1590636
user1590636

Reputation: 1194

C# LINQ ternary operator as a switchcase inside a foreach

i am using LINQ and HtmlAgilitypack to create a datatable out of an HTML. the following gets the html table headers and constructs the datatable columns:

var nodes = htmlDoc.DocumentNode.SelectNodes("//table[@class='ps-sellers-table crts']/tr");
             nodes[0].Elements("th")
            .Skip(0)
            .Select(th => th.InnerText
            .Trim())
            .ToList()
            .ForEach(header => dt.Columns.Add(header));

so far its working perfectly except i need some customization.

  1. chosing what columns to be added.
  2. and specifying the column type.

this select statement will do the 2 things above:

switch (header)
            {
                case ("id") : dt.Columns.Add(header,typeof(int)); break;
                case ("name") : dt.Columns.Add(header,typeof(string)); break;
                case ("price") : dt.Columns.Add(header,typeof(decimal)); break;
                case ("shipping") : dt.Columns.Add(header,typeof(decimal)); break;
                default : //skip the column and dont add it
            }

however i am really new to LINQ and C#, and i want to implement the above switch case inside the foreach in the first snippet, i know i should use ternary operator, but i am not sure about the sytax.

Upvotes: 2

Views: 2328

Answers (2)

sa_ddam213
sa_ddam213

Reputation: 43596

You could just add the switch to the foreach, not sure why you have to use the ternary operator

.ToList().ForEach(header =>
{
    switch (header)
    {
       case ("id"): dt.Columns.Add(header, typeof(int)); break;
       case ("name"): dt.Columns.Add(header, typeof(string)); break;
       case ("price"): dt.Columns.Add(header, typeof(decimal)); break;
       case ("shipping"): dt.Columns.Add(header, typeof(decimal)); break;
       default: break; //skip the column and dont add it
    }
});

Upvotes: 1

Reed Copsey
Reed Copsey

Reputation: 564413

I would wrap the switch into a method, and then call the method from within your select statement.

My version would look like:

var nodes = htmlDoc.DocumentNode.SelectNodes("//table[@class='ps-sellers-table crts']/tr");
         nodes[0].Elements("th")
        .Select(th => th.InnerText.Trim());

foreach(var node in nodes)
    AddColumnToDataTable(node, dt);

Note that there's no need to Skip(0), and calling ToList() just to use List<T>.ForEach reduces readability and adds overhead. I personally prefer just using a normal foreach.

That being said, your method could be refactored into using a Dictionary<string, Type> instead. If you add this to your class:

Dictionary<string, Type> typeLookup;
// In your constructor:

public YourClass()
{
    typeLookup.Add("id", typeof(int));
    typeLookup.Add("name", typeof(string));
    typeLookup.Add("price", typeof(decimal));
    typeLookup.Add("shipping", typeof(decimal));
}

You could then write your method as:

void AddColumnToDataTable(string columnName, DataTable table)
{
    table.Columns.Add(columnName, typeLookup[columnName]);
}

Upvotes: 5

Related Questions