我想截断一个字符串,使其长度不超过给定值。我正在向数据库表写入数据,并希望确保写入的值满足列数据类型的约束。

例如,如果我能写以下内容,那就太好了:

string NormalizeLength(string value, int maxLength)
{
    return value.Substring(0, maxLength);
}

不幸的是,这会引发异常,因为maxLength通常超过字符串值的边界。当然,我可以写一个像下面这样的函数,但我希望这样的东西已经存在了。

string NormalizeLength(string value, int maxLength)
{
    return value.Length <= maxLength ? value : value.Substring(0, maxLength);
} 

执行此任务的难以捉摸的API在哪里?有吗?


当前回答

这是我通常使用的代码:

string getSubString(string value, int index, int length)
        {
            if (string.IsNullOrEmpty(value) || value.Length <= length)
            {
                return value;
            }
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (int i = index; i < length; i++)
            {
                sb.AppendLine(value[i].ToString());
            }
            return sb.ToString();
        }

其他回答

我想我应该加入我的实现,因为我相信它涵盖了其他人所涉及的所有情况,并且以一种简洁的方式做到了这一点,仍然是可读的。

public static string Truncate(this string value, int maxLength)
{
    if (!string.IsNullOrEmpty(value) && value.Length > maxLength)
    {
        return value.Substring(0, maxLength);
    }

    return value;
}

该解决方案主要构建在Ray的解决方案之上,并通过使用This关键字将该方法作为扩展方法使用,就像LBushkin在他的解决方案中所做的那样。

请注意,截断字符串不仅仅意味着仅以指定的长度切割字符串,而且必须注意不要分割单词。

Eg字符串:这是一个测试字符串。

我想把它剪到11点。如果我们使用上面给出的任何一种方法,结果将是

这是一个

这不是我们想要的

我使用的方法可能也不是那么完美,但它可以处理大多数情况

public string CutString(string source, int length)
{
        if (source== null || source.Length < length)
        {
            return source;
        }
        int nextSpace = source.LastIndexOf(" ", length);
        return string.Format("{0}...", input.Substring(0, (nextSpace > 0) ? nextSpace : length).Trim());
} 

这是我通常使用的代码:

string getSubString(string value, int index, int length)
        {
            if (string.IsNullOrEmpty(value) || value.Length <= length)
            {
                return value;
            }
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (int i = index; i < length; i++)
            {
                sb.AppendLine(value[i].ToString());
            }
            return sb.ToString();
        }

因为性能测试很有趣:(使用linqpad扩展方法)

var val = string.Concat(Enumerable.Range(0, 50).Select(i => i % 10));

foreach(var limit in new[] { 10, 25, 44, 64 })
    new Perf<string> {
        { "newstring" + limit, n => new string(val.Take(limit).ToArray()) },
        { "concat" + limit, n => string.Concat(val.Take(limit)) },
        { "truncate" + limit, n => val.Substring(0, Math.Min(val.Length, limit)) },
        { "smart-trunc" + limit, n => val.Length <= limit ? val : val.Substring(0, limit) },
        { "stringbuilder" + limit, n => new StringBuilder(val, 0, Math.Min(val.Length, limit), limit).ToString() },
    }.Vs();

截断法“明显”更快。# microoptimization

早期

truncate10 5788滴答流逝(0.5788 ms) [10K次,5.788E-05 ms /次] smart-trunc10 8206滴答流逝(0.8206 ms) [10K次,8.206E-05 ms /次] stringbuilder10 10557滴答流逝(1.0557 ms) [10K次,0.00010557 ms /次] concat10 45495滴答流逝(4.5495 ms) [10K次,0.00045495 ms /次] 时间流逝(7.2535 ms) [10K次,0.00072535 ms /次]

Late

truncate44 8835滴答流逝(0.8835 ms) [10K次,8.835E-05 ms /次] 13106滴答流逝(1.3106 ms) [10K次,0.00013106 ms /次] smart-trunc44 14821滴答流逝(1.4821毫秒)[10K次,0.00014821毫秒/次] 时间流逝(14.4324 ms) [10K次,0.00144324 ms /次] concat44 174610滴答流逝(17.461毫秒)[每10K次,0.0017461毫秒]

太长时间

smart-trunc64 6944滴答流逝(0.6944毫秒)[在10K次中,6.944E-05毫秒每] truncate64 7686滴答流逝(0.7686 ms) [10K次,7.686E-05 ms /次] stringbuilder64 13314滴答流逝(1.3314 ms) [10K次,0.00013314 ms /次] 时间流逝(17.7481 ms) [10K次,0.00177481 ms /次] concat64 241601滴答流逝(24.1601毫秒)[每10K次,0.00241601毫秒]

我知道这是一个老问题,但这里有一个很好的解决方案:

public static string Truncate(this string text, int maxLength, string suffix = "...")
{
    string str = text;
    if (maxLength > 0)
    {
        int length = maxLength - suffix.Length;
        if (length <= 0)
        {
            return str;
        }
        if ((text != null) && (text.Length > maxLength))
        {
            return (text.Substring(0, length).TrimEnd(new char[0]) + suffix);
        }
    }
    return str;
}

var myString = "hello world"
var myTruncatedString = myString.Truncate(4);

返回:你好……