简体   繁体   English

比较两个逗号分隔的字符串以进行匹配的最短代码是什么?

[英]What is the shortest code to compare two comma-separated strings for a match?

The method below called UserCanAccessThisPage is based on the following logic: each user and each page has a list of groups.下面称为UserCanAccessThisPage的方法基于以下逻辑:每个用户和每个页面都有一个组列表。 If any of these match, the user has access to the page.如果其中任何一项匹配,则用户可以访问该页面。

The code below does what I want, but my solution is very C# 1 (or C# 2, at least I didn't use ArrayList).下面的代码做了我想要的,但我的解决方案是非常 C# 1 (或 C# 2,至少我没有使用 ArrayList)。

Can anyone refactor this so it is more straight-forward, eg using lambdas to do away with the two methods?任何人都可以重构这个使其更直接,例如使用 lambdas 来取消这两种方法吗? I just can't get the syntax to do it.我只是无法获得这样做的语法。

using System;
using System.Collections.Generic;
using System.Linq;

namespace TestCompare2343
{
    class Program
    {
        static void Main(string[] args)
        {

            string anonymousUserAccessGroups = "loggedOutUsers";
            string normalUserAccessGroups = "loggedInUsers, members";
            string developerUserAccessGroups = "loggedInUsers, members, administrators, developers";

            string loginPageAccessGroups = "loggedOutUsers";
            string logoutPageAccessGroups = "loggedInUsers";
            string memberInfoPageAccessGroups = "members";
            string devPageAccessGroups = "developers";

            //test anonymousUser
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(anonymousUserAccessGroups, loginPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(anonymousUserAccessGroups, logoutPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(anonymousUserAccessGroups, memberInfoPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(anonymousUserAccessGroups, devPageAccessGroups));
            Console.WriteLine("---");

            //test anonymousUser
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(normalUserAccessGroups, loginPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(normalUserAccessGroups, logoutPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(normalUserAccessGroups, memberInfoPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(normalUserAccessGroups, devPageAccessGroups));
            Console.WriteLine("---");

            //test anonymousUser
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(developerUserAccessGroups, loginPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(developerUserAccessGroups, logoutPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(developerUserAccessGroups, memberInfoPageAccessGroups));
            Console.WriteLine(StringHelpers.UserCanAccessThisPage(developerUserAccessGroups, devPageAccessGroups));
            Console.WriteLine("---");

            Console.ReadLine();

        }
    }

    public class StringHelpers
    {
        public static bool UserCanAccessThisPage(string userAccessGroups, string pageItemAccessGroups)
        {
            List<string> userAccessGroupsList = StringHelpers.SplitAndTrimCommaDelimitedString(userAccessGroups);
            List<string> pageItemAccessGroupList = StringHelpers.SplitAndTrimCommaDelimitedString(pageItemAccessGroups);

            foreach (string userAccessGroup in userAccessGroupsList)
            {
                foreach (string pageItemAccessGroup in pageItemAccessGroupList)
                {
                    if (userAccessGroup == pageItemAccessGroup)
                        return true;
                }
            }

            return false;
        }

        public static List<string> SplitAndTrimCommaDelimitedString(string line)
        {
            List<string> piecesWithSpaces = line.Split(',').ToList<string>();
            List<string> piecesWithoutSpaces = new List<string>();
            foreach (string pieceWithSpace in piecesWithSpaces)
            {
                piecesWithoutSpaces.Add(pieceWithSpace.Trim());
            }
            return piecesWithoutSpaces;
        }
    }
}

Answer:回答:

Fredrik had the most concise code that solved the original task above: Fredrik 有最简洁的代码来解决上面的原始任务:

public static bool UserCanAccessThisPage(string userAccessGroups, string pageItemAccessGroups)
{
    return userAccessGroups
        .Split(',')
        .Select(s => s.Trim())
        .Contains(pageItemAccessGroups);
}

The code I used:我使用的代码:

But Shaul was correct in assuming that the PageItems can also have multiple entries, eg "members,guests", and so I actually used Shaul's code:但是 Shaul 假设 PageItems 也可以有多个条目是正确的,例如“成员,客人”,所以我实际上使用了 Shaul 的代码:

public static bool UserCanAccessThisPage(string userAccessGroups, string pageItemAccessGroups) {
  List<string> userAccessGroupsList = StringHelpers.SplitAndTrimCommaDelimitedString(userAccessGroups);
  List<string> pageItemAccessGroupList = StringHelpers.SplitAndTrimCommaDelimitedString(pageItemAccessGroups);
  return userAccessGroupsList.Any(userAccessGroup => pageItemAccessGroupList.Any(pageItemAccessGroup => userAccessGroup == pageItemAccessGroup));
}

public static List<string> SplitAndTrimCommaDelimitedString(string line) {
  return line.Split(',').Select(s => s.Trim()).ToList();
}

OK, you said you wanted compact...!好吧,你说你想要紧凑......! :) :)

public static bool UserCanAccessThisPage(string userAccessGroups, string pageItemAccessGroups) {
  List<string> userAccessGroupsList = StringHelpers.SplitAndTrimCommaDelimitedString(userAccessGroups);
  List<string> pageItemAccessGroupList = StringHelpers.SplitAndTrimCommaDelimitedString(pageItemAccessGroups);
  return userAccessGroupsList.Any(userAccessGroup => pageItemAccessGroupList.Any(pageItemAccessGroup => userAccessGroup == pageItemAccessGroup));
  // or:
  // return userAccessGroupsList.Any(userAccessGroup => pageItemAccessGroupList.Contains(userAccessGroup));
}

public static List<string> SplitAndTrimCommaDelimitedString(string line) {
  return line.Split(',').Select(s => s.Trim()).ToList();
}

StringHelpers could look like this: StringHelpers 可能如下所示:

public class StringHelpers
{
    private static readonly char[] separator = ",".ToCharArray();
    public static bool UserCanAccessThisPage(
        string userAccessGroups, 
        string pageItemAccessGroups)
    {
        return userAccessGroups
            .Split(separator) // split on comma
            .Select(s => s.Trim()) // trim elements
            .Contains(pageItemAccessGroups); // match
    }
}
public static bool UserCanAccessThisPage(
    string userAccessGroups, string pageItemAccessGroups)
{
    HashSet<string> u = new HashSet<string>(
        userAccessGroups.Split(',').Select(x => x.Trim()));
    return u.Overlaps(pageItemAccessGroups.Split(',').Select(x => x.Trim()));
}

Once you have the two IEnumerable<string> s, you can use the Intersect function:一旦你有了两个IEnumerable<string> ,你就可以使用Intersect函数:

return userGroups.Intersect(pageGroups).Count > 0;

This is in case you need the full list of permissions for the user on the page.这是为了防止您需要页面上用户的完整权限列表。
However, I'd go with Shaul's example: the Any function is faster, it should stop at the first match.但是,我会使用 Shaul 的示例: Any函数更快,它应该在第一场比赛时停止。

Something like (sorry no IDE to hand)类似的东西(抱歉没有 IDE)

public static bool UserCanAccessThisPage(string userAccessGroups, string pageItemAccessGroups)
{
    List<string> userAccessGroupsList = StringHelpers.SplitAndTrimCommaDelimitedString(userAccessGroups);
    List<string> pageItemAccessGroupList = StringHelpers.SplitAndTrimCommaDelimitedString(pageItemAccessGroups);

    return userAccessGroupsList.Where(
                          uag => pageItemAccessGroupList.Contains(uag)).Count > 0;
}

public static List<string> SplitAndTrimCommaDelimitedString(string line)
{
    return line.Split(',').Select(s => s.Trim()).ToList<string>();
}

I really don't see a big problem with it having two methods, since the functionality is nicely separated, but I guess you could move the code from the second method inline to the first if you really want to.我真的不认为它有两种方法有什么大问题,因为功能很好地分开了,但我想如果你真的想要的话,你可以将代码从第二个方法内联移动到第一个方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM