比较字符串是否相等

Compare strings for equality

我想比较一组字符串和 return 相等的部分,直到出现不相等的部分。 (并删除尾随空格)。

示例:

List<string> strList = new List<string>
{
    "string xyz stop",
    "string abc stop",
    "string   qrt stop"
};

string result = GetEqualName(strList); // This should return "string"

我做了以下有效的方法

string GetEqualName(IEnumerable<string> strList)
{
    string outString = "";
    bool firstTime = true;
    foreach (var subString in strList)
    {
        if (firstTime)
        {
            outString = subString;
            firstTime = false;
        }
        else
        {
            string stringBuilder = "";
            for (int i = 0; i < outString.Count(); i++)
            {
                if (outString[i] == subString[i])
                    stringBuilder = stringBuilder + outString[i];
                else
                    break;
            }
            outString = stringBuilder;
        }
    }
    outString = outString.TrimEnd(' '); // Remove traling whitespace
    return outString;
}

我只是觉得这是几行就可以完成的事情,我做得有点过头了。大家有什么建议吗?

您可以 Zip 将两个字符串放在一起,取相等的对,然后创建一个包含这些字符的字符串。

public static string LargestCommonPrefix(string first, string second)
{
    return new string(first.Zip(second, Tuple.Create)
        .TakeWhile(pair => pair.Item1 == pair.Item2)
        .Select(pair => pair.Item1)
        .ToArray());
}

一旦你解决了结合两个字符串的问题,你就可以轻松地将它应用到字符串序列中:

public static string LargestCommonPrefix(IEnumerable<string> strings)
{
    return strings.Aggregate(LargestCommonPrefix);
}

这个小功能和你的版本基本一样,但是更短。

string GetEqualName(IEnumerable<string> strList)
{
    int limit = strList.Min(s => s.Length);

    int i = 0;
    for (; i < limit; i++)
    {
        if (strList.Select(s => s.Substring(0,i+1)).Distinct().Count() > 1)
        {
            break;
        }
    }
    return strList.First().Substring(0, i).Trim();
}

这是一种不同的方法,可以满足您的需求。我使用 HashSet<string>:

从左到右寻找最长的公共子串
string GetCommonStartsWith(IEnumerable<string> strList, StringComparer comparer = null)
{
    if(!strList.Any() || strList.Any(str => string.IsNullOrEmpty(str)))
        return null;
    if(!strList.Skip(1).Any())
        return strList.First(); // only one

    if(comparer == null) comparer = StringComparer.CurrentCulture;
    int commonLength = strList.Min(str => str.Length);

    for (int length = commonLength; length > 0; length--)
    {
        HashSet<string> duptester = new HashSet<string>(comparer);
        string first = strList.First().Substring(0, length).TrimEnd();
        duptester.Add(first);
        bool allEqual = strList.Skip(1)
            .All(str => !duptester.Add(str.Substring(0, length).TrimEnd()));
        if (allEqual)
            return first;
    }
    return null;
}

这是一个比其他一些答案使用更少 LINQ 并且可能性能更高的版本。

string GetEqualName(IEnumerable<string> strList)
{
    StringBuilder builder = new StringBuilder();
    int minLength = strList.Min(s => s.Length);

    for (int i = 0; i < minLength; i++)
    {
        char? c = null;
        foreach (var s in strList)
        {
            if (c == null)
                c = s[i];
            else if (s[i] != c)
                return builder.ToString().TrimEnd();
        }
        builder.Append(c);
    }
    return builder.ToString().TrimEnd();
}