2

I have some code that will loop over DataRows and will split a pipe delimited column in the DataRow into an array, and then into a List<string>.

Is there a better way to do this using LINQ? I've tried but got nowhere!

List<string> allSizes = new List<string>();

foreach (DataRow resultRow in results.Rows)
{
    if (resultRow["Sizes"] != DBNull.Value)
    {
        string[] sizes = resultRow["Sizes"].ToString().Split('|');
        foreach (string size in sizes)
        {
            if (!allSizes.Contains(size))
            {
                allSizes.Add(size);
            }
        }
    }
}
1
  • Note that using Contains on a List isn't particularly efficient. Considering that it's likely that the data set could get large, and you check whether it's in the list or not for each item, that could get expensive. It's better to use a set-based data structure to perform a Distinct, which is what you're doing, and what the LINQ Distinct method does. Commented Oct 22, 2012 at 19:08

4 Answers 4

10
var allSizes = results.Rows.Cast<DataRow>()
    .Where(row => row["Sizes"] != DBNull.Value)
    .SelectMany(row => row["Sizes"].ToString().Split('|'))
    .Distinct()
    .ToList();
Sign up to request clarification or add additional context in comments.

1 Comment

Extension methods look much better :) +1
0

Here is the LINQ version but personally I don't find it much cleaner:

var allSizes = new List<string>();

foreach (
    string size in 
    from DataRow resultRow in results.Rows 
    where resultRow["Sizes"] != DBNull.Value 
    select resultRow["Sizes"].ToString().Split('|') into sizes 
    from size in sizes where !allSizes.Contains(size) 
    select size) {
    allSizes.Add(size);
}

1 Comment

As noted to OP, performing a contains on a List of nontrivial size isn't a cheap operation; you should be putting the items into a set-based data structure to perform the distinct.
0

Something like this.

var linqSizes =
    from row in results.Rows
    where row["Sizes"] != DBNull.Value
    let sizes = row["Sizes"].ToString().Split('|')
    from size in sizes
    group size by size into g
    select g.Key;

The variable linqSizes will contain the same elements as your variable allSizes.

Comments

0

Strong-typed DataRow and LINQ:

dt.Rows.OfType<DataRow>().Where(r => r["Sizes"] != DBNull.Value)
      .SelectMany(r=>r.Field<string>("Sizes").Split('|')
      .Distinct().ToList();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.