检查列表中的任何项是否与另一个列表中的任何项匹配

时间:2010-03-24 13:46:04

标签: c# algorithm .net-3.5

一位同事让我写一个单行代替以下方法:

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和我想出了这个:

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

有更好的方法吗?

2 个答案:

答案 0 :(得分:23)

鉴于LINQ,是的:

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

请注意,除了使用Intersect将其转换为O(m)+ O(n)而不是O(m * n)之外,使用Any比使用{{1}更有效 - 一旦找到第一场比赛,你就知道了答案。

答案 1 :(得分:2)

您可以编写一个可以处理许多情况的通用扩展方法。功能本身就是一条线。

/// <summary>
/// Compares both lists to see if any item in the enumerable 
/// equals any item in the other enumerable. 
/// </summary>
public static bool AnyItem<T>(this IEnumerable<T> source, IEnumerable<T> other, IEqualityComparer<T> comparer = null)
{
    return (comparer == null ? source.Intersect(other) : source.Intersect(other, comparer)).Any();
}

较旧,效率较低的答案

public static bool AnyItem<T>(this IEnumerable<T> source, IEnumerable<T> other)
{
    return source.Any(s => other.Any(o => EqualityComparer<T>.Default.Equals(s, o)));
}

认为这也比当前答案更有效(它不是)。我必须检查EqualityComparer是否昂贵,但我愿意怀疑它。

您还可以扩展此函数以接受一个表达式,该表达式将评估要包含对象的枚举的要比较的属性。

public static bool AnyItem<T, TResult>(
        this IEnumerable<T> source, 
        IEnumerable<T> other, 
        Expression<Func<T, TResult>> compareProperty = null)
{
    if (compareProperty == null)
    {
        return source.Any(s => other.Any(o => EqualityComparer<T>.Default.Equals(s, o)));
    }

    return source.Any(s => other.Any(o => 
                    EqualityComparer<TResult>.Default.Equals(
                    s.GetPropertyValue(compareProperty),
                    o.GetPropertyValue(compareProperty))));
}

public static TValue GetPropertyValue<TTarget, TValue>(
    this TTarget target, Expression<Func<TTarget, TValue>> memberLamda)
{
    var memberSelectorExpression = memberLamda.Body as MemberExpression;
    var property = memberSelectorExpression?.Member as PropertyInfo;
    return (TValue)property?.GetValue(target);
}