【问题标题】:LINQ way to check Contains in a List (regardless of white spaces)LINQ 检查列表中包含的方法(不考虑空格)
【发布时间】:2012-12-06 12:31:32
【问题描述】:

我有以下代码来检查 userRoles 集合是否具有authorizedRolesList 中的任何值。如果 userRoleName 有空格,则它不起作用。

LINQ 最有效的处理方式是什么?

代码

        List<string> authorizedRolesList = null;
        string AuthorizedRolesValues = "A, B ,C,D";
        if (!String.IsNullOrEmpty(AuthorizedRolesValues))
        {
            authorizedRolesList = new List<string>((AuthorizedRolesValues).Split(','));
        }

        string userRoleName = String.Empty;

        Collection<string> userRoles = new Collection<string>();
        userRoles.Add("B   ");

        bool isAuthorizedRole = false;
        if (userRoles != null)
        {
            foreach (string roleName in userRoles)
            {
                userRoleName = roleName.Trim();
                if (authorizedRolesList != null)
                {
                    //Contains Check
                    if (authorizedRolesList.Contains(userRoleName))
                    {
                        isAuthorizedRole = true;
                    }
                }

            }
        }

参考:

  1. When to use .First and when to use .FirstOrDefault with LINQ?
  2. Intersect with a custom IEqualityComparer using Linq
  3. Ignoring hyphen in case insensitive dictionary keys
  4. C#: splitting a string and not returning empty string
  5. When does IEnumerable.Any(Func) return a value?
  6. Is IEnumerable.Any faster than a for loop with a break?

【问题讨论】:

  • 使用 Enumerable.Any 方法
  • 下面的答案几乎涵盖了它,但是,如果字符串中间有空格(如“Role A”),那么 .Trim 将不起作用。它只删除字符串开头和结尾的空格。您可以使用 String.Replace(" ", "") 来处理这种情况。

标签: c# linq


【解决方案1】:

我猜最有效的 LINQ 方式在这里表示最易读。

显而易见的方法是在调用Split() 时使用StringSplitOptions.RemoveEmptyEntries,而不是一开始就存储空格。

authorizedRolesList = AuthorizedRolesValues.Split(new []{','}, StringSplitOptions.RemoveEmptyEntries);

但如果出于某种原因您想保留额外的空格或无法更改 authorizedRolesList 中的条目,您可以轻松更改 if 子句

if (authorizedRolesList.Contains(userRoleName))

if (authorizedRolesList.Any(x => x.Trim() == userRoleName))

顺便说一句,谈论 LINQ:

你可以用

替换你的代码
bool isAuthorizedRole = userRoles.Any(ur => authorizedRolesList.Any(ar => ar.Trim() == ur.Trim()))

如果您确保 userRolesauthorizedRolesList 不是 null(请改用空集合)。

恕我直言,更具可读性的内容类似于

bool isAuthorizedRole = userRoles.Intersect(authorizedRolesList, new IgnoreWhitespaceStringComparer()).Any();

IgnoreWhitespaceStringComparer 的样子

class IgnoreWhitespaceStringComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.Trim().Equals(y.Trim());
    }

    public int GetHashCode(string obj)
    {
        return obj.Trim().GetHashCode();
    }
}

【讨论】:

  • 谢谢。 “任何”是否遍历相交结果中的所有元素?还是只检查是否存在值? [我指的是IEqualityComparer方法]
  • Any 遍历集合,但当有满足条件的元素时停止迭代。所以在最好的情况下,它只需要检查第一个元素;在最坏的情况下,它必须检查所有元素。
  • 其实我还有一个要求。我需要获得第一个匹配的角色名称。有没有办法在不将intersect 结果存储在变量中的情况下获得它?
  • 那我建议你使用userRoles.Intersect(authorizedRolesList, new IgnoreWhitespaceStringComparer()).FirstOrDefault()。这将返回第一个匹配的角色名(如果有),如果没有匹配则返回 null
【解决方案2】:

只需像这样修剪列表中的每个条目:

authorizedRolesList.ForEach(a => a = a.Trim());

【讨论】:

    【解决方案3】:

    尝试像这样在拆分字符串时删除空格并使用 Trim()

     List<string> authorizedRolesList = null;
        string AuthorizedRolesValues = "A, B ,C,D";
        if (!String.IsNullOrEmpty(AuthorizedRolesValues))
        {
            string[] separators = {","};
            authorizedRolesList = new List<string>(
               ((AuthorizedRolesValues)
                      .Split(separators , StringSplitOptions.RemoveEmptyEntries))
                      .Select(x => x.Trim());
        }
    

    然后在下面的代码中使用 Trim()

                    //Contains Check
                    if (authorizedRolesList.Contains(userRoleName.Trim()))
                    {
                        isAuthorizedRole = true;
                    }
    

    【讨论】:

      【解决方案4】:
              string authorizedRolesValues = "A, B ,C,D";
      
              var authorizedRolesList = authorizedRolesValues
                  .Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
                  .Select(role => role.Trim());
      
              var userRoles = new Collection<string> {"B   "};
      
              bool isAuthorizedRole = userRoles
                  .Select(roleName => roleName.Trim())
                  .Any(authorizedRolesList.Contains);
      

      【讨论】:

        【解决方案5】:

        如何也修剪原始列表?

        authorizedRolesList = new List&lt;string&gt;((AuthorizedRolesValues).Split(',').Select(x =&gt; x.Trim()));

        【讨论】:

          【解决方案6】:

          试试这个

          bool ifExists = userRoles.Any(AuthorizedRolesValues.Split(',').Select(val => val = val.trim());
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-27
            • 1970-01-01
            • 2022-11-17
            • 2012-07-24
            • 1970-01-01
            • 1970-01-01
            • 2017-11-10
            • 2019-01-07
            相关资源
            最近更新 更多