cbr
cbr

Reputation: 13662

How could I convert these foreach loops into a LINQ-expression?

I used ReSharper to inspect the code issues in my project and it notified me that the following loop could be converted into a LINQ-expression:

var dictionary = new Dictionary<string, string[]>
{
    { "400", new[] { "12345", "54321", "51423" } },
    { "500", new[] { "67890", "09876", "63727" } },
    { "600", new[] { "41713", "98234", "96547" } },
    { "700", new[] { "00000", "67990", "83752" } }
};

// ...

var targetValue = "41713";
foreach (string group in dictionary.Keys)
{
    foreach (string name in dictionary[group])
    {
        if (name == targetValue)
            return group;
    }
}
return "User";

The loop basically checks the dictionary's values (string arrays) to see if targetValue belongs to any of them and returns the key of that array if found inside.

I tried doing the following, but clearly it just returns the value inside if its value is equivalent to targetValue.

var r = dictionary
        .SelectMany(t => t.Value)
        .FirstOrDefault(t => t == targetValue);

Upvotes: 1

Views: 2829

Answers (3)

terrybozzio
terrybozzio

Reputation: 4532

This will also get the desired value back or null if it does not exist:

EDIT:

var result = dictionary.SkipWhile(n => !n.Value.Contains(myValue)).FirstOrDefault().Key;
//another way to get the key
//var result = dictionary.SingleOrDefault(n => n.Value.Contains(myValue)).Key;
if (result != null)
{
   //do whatever with the result variable here
}

Upvotes: 0

Tim Schmelter
Tim Schmelter

Reputation: 460238

So you want to get the first key in the dictionary which string[]-value contains a given value?

var pairs = dictionary.Where(kv => kv.Value.Contains(myValue));
if (pairs.Any())
{
    string group = pairs.First().Key;
}

or less readable but a little bit more efficient since it executes the query only once:

var pair = dictionary.FirstOrDefault(kv => kv.Value.Contains(myValue));
if (!pair.Equals(default(KeyValuePair<string, string[]>)))
{
    string group = pair.Key;
}

last but not least another approach which is my favorite and also uses the "User"-default:

string group = dictionary.Where(kv => kv.Value.Contains(myValue))
    .Select(kv=> kv.Key)
    .DefaultIfEmpty("User")
    .First();

Upvotes: 4

Alexandr Sulimov
Alexandr Sulimov

Reputation: 1924

var r = dictionary.FirstOrDefault(
    x => x.Value.FirstOrDefault(y => y == myValue) != null);

Upvotes: 1

Related Questions