views:

117

answers:

1

A coleague asked me to write a one-liner to replace the following method:

public static bool IsResourceAvailableToUser(IEnumerable<string> resourceRoles, IEnumerable<string> userRoles)
{
    foreach (var userRole in userRoles)
        foreach (var resourceRole in resourceRoles)
            if (resourceRole == userRole)
                return true;
    return false;
}

Resharper and I came up with this:

public static bool IsResourceAvailableToUser(IEnumerable<string> resourceRoles, IEnumerable<string> userRoles)
{
    return userRoles.Where(resourceRoles.Contains).Count() > 0;
}

Is there a better way?

+10  A: 

Given LINQ, yes:

return userRoles.Intersect(resourceRoles).Any();

Note that aside from the use of Intersect to turn it into O(m) + O(n) instead O(m * n), using Any is more efficient than using Count() > 0 - you know the answer as soon as you've found the first match.

Jon Skeet
Thank you! I've learned something new today.
grenade
tafa
Speaking out of interest as a non-C# person (I caught the "algorithm" tag), what guarantees that this is linear? Surely the collections need to be sorted for that: are they?
Steve Jessop
+1 Wow... Jon, we may need to nickname you Captain LINQ :)
Repo Man
@Steve: It uses a hash set, basically - building a hash set from `userRoles` should be amortized O(m), and looking up each item from `resourceRoles` within the hash set should be O(n) in total.
Jon Skeet
D'oh. Non-online algorithms also exist ;-) Thanks.
Steve Jessop