代码之家  ›  专栏  ›  技术社区  ›  grenade

检查列表中的任何项目是否与其他列表中的任何项目匹配

  •  11
  • grenade  · 技术社区  · 14 年前

    一个Coleague让我写一行代码来替换以下方法:

    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;
    }
    

    我和雷斯哈珀想到了:

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

    有更好的方法吗?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Zachary Dow    7 年前

    您可以编写一个处理许多情况的通用扩展方法。函数本身的肉是一行。

    /// <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)));
    }
    

    认为 这也比目前的答案更有效 (不是)。我得检查一下买均等比较器是否很贵,但我愿意怀疑这一点。


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

    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);
    }
    
        2
  •  23
  •   Jon Skeet    14 年前

    给定LINQ,是:

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

    注意,除了使用 Intersect 要将其转换为o(m)+o(n),请使用 Any 比使用更有效 Count() > 0 -你一找到第一个匹配项就知道答案了。