我想截断一个字符串,使其长度不超过给定值。我正在写一个数据库表,并希望确保我写的值符合列数据类型的约束。
例如,如果我能写下以下内容会很好:
string NormalizeLength(string value, int maxLength)
{
return value.Substring(0, maxLength);
}
不幸的是,这引发了异常,因为maxLength
通常超出了字符串value
的边界。当然,我可以编写如下的函数,但我希望这样的东西已经存在。
string NormalizeLength(string value, int maxLength)
{
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
}
执行此任务的难以捉摸的API在哪里?有吗?
答案 0 :(得分:542)
遗憾的是,字符串上没有Truncate()
方法。您必须自己编写这种逻辑。但是,你可以做的是将它包装在扩展方法中,这样你就不必在任何地方复制它:
public static class StringExt
{
public static string Truncate(this string value, int maxLength)
{
if (string.IsNullOrEmpty(value)) return value;
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
}
}
现在我们可以写:
var someString = "...";
someString = someString.Truncate(2);
答案 1 :(得分:111)
或者代替三元运算符,您可以使用Math.min
public static class StringExt
{
public static string Truncate( this string value, int maxLength )
{
if (string.IsNullOrEmpty(value)) { return value; }
return value.Substring(0, Math.Min(value.Length, maxLength));
}
}
答案 2 :(得分:35)
我想我会投入我的实现,因为我相信它涵盖了其他人所触及的所有案例,并且以简洁的方式进行,但仍然可读。
public static string Truncate(this string value, int maxLength)
{
if (!string.IsNullOrEmpty(value) && value.Length > maxLength)
{
return value.Substring(0, maxLength);
}
return value;
}
此解决方案主要以Ray's solution为基础,并在其解决方案中使用 this 关键字作为LBushkin does打开了用作扩展方法的方法。
答案 3 :(得分:30)
在.NET 4.0中,您可以使用Take
方法:
string.Concat(myString.Take(maxLength));
未进行效率测试!
答案 4 :(得分:27)
你可以使用LINQ ...它不需要检查字符串长度。不可否认,也许不是最有效的,但它很有趣。
string result = string.Join("", value.Take(maxLength)); // .NET 4 Join
或
string result = new string(value.Take(maxLength).ToArray());
答案 5 :(得分:21)
因为性能测试很有趣:(使用linqpad extension methods)
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();
truncate
方法“显着”更快。 #microoptimization
早期
- truncate10 5788蜱已过去(0.5788毫秒)[以10K代表为单位,每年5.788E-05毫秒]
- smart-trunc10 8206经过时间(0.8206毫秒)[10K代表,每个8.206E-05毫秒]
- stringbuilder10 10557经过时间(1.0557毫秒)[10K代表,每个0.00010557毫秒]
- concat10 45495经过时间(4.5495毫秒)[10K代表,每个0.00045495毫秒]
- newstring10 72535经过时间(7.2535毫秒)[10K代表,每个0.00072535毫秒]
晚
- truncate44 8835 ticks(0.8835 ms)[10K reps,8.835E-05 ms per]
- stringbuilder44 13106 ticks逝去(1.3106 ms)[10K reps,0.00013106 ms per]
- smart-trunc44 14821 ticks已过去(1.4821 ms)[以10K reps计,每个0.00014821 ms]
- newstring44 144324 ticks逝去(14.4324 ms)[10K reps,0.00144324 ms per]
- concat44 174610经过时间(17.461毫秒)[10K代表,每个0.0017461毫秒]
太长
- smart-trunc64 6944 ticks已过去(0.6944 ms)[以10K代表为单位,每页6.944E-05 ms]
- truncate64 7686 ticks(0.7686 ms)[10K reps,7.686E-05 ms per]
- stringbuilder64 13314 ticks已过去(1.3314 ms)[以10K代表为单位,每个0.00013314 ms]
- newstring64 177481经过时间(17.7481 ms)[以10K代表计,每人0.00177481毫秒]
- concat64 241601经过时间(24.1601 ms)[以10K代表,每个0.00241601毫秒]
答案 6 :(得分:12)
似乎还没有人发布这个:
public static class StringExt
{
public static string Truncate(this string s, int maxLength)
{
return s != null && s.Length > maxLength ? s.Substring(0, maxLength) : s;
}
}
使用&amp;&amp;运算符使其略微优于接受的答案。
答案 7 :(得分:11)
.NET Framework有一个API来截断这样的字符串:
Microsoft.VisualBasic.Strings.Left(string, int);
但是在C#应用程序中,你可能更喜欢自己动手而不是依赖于Microsoft.VisualBasic.dll,它的主要存在是后向兼容性。
答案 8 :(得分:9)
我在一行中做了我这样的
value = value.Length > 1000 ? value.Substring(0, 1000) : value;
答案 9 :(得分:5)
在C#8中,可以使用新的Ranges功能...
value = value[..Math.Min(30, value.Length)];
答案 10 :(得分:5)
C#6的Null传播算子的类似变体
public static string Truncate(this string value, int maxLength)
{
return value?.Length <= maxLength ? value : value?.Substring(0, maxLength);
}
请注意,我们实际上是在这里检查value
是否为空两次。
答案 11 :(得分:5)
我知道这是一个老问题,但这是一个很好的解决方案:
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);
返回:你好......
答案 12 :(得分:4)
另一种解决方案:
return input.Substring(0, Math.Min(input.Length, maxLength));
答案 13 :(得分:4)
2016年C#字符串仍然没有Truncate方法。 但是 - 使用C#6.0语法:
<div>
<h2>header info</h2>
<p>some text comes here</p>
<a href="/<% this.fileName() %>">now I want this url to be a link to a seperate page that only loads one template<a>
</div>
它就像一个魅力:
public static class StringExtension
{
public static string Truncate(this string s, int max)
{
return s?.Length > max ? s.Substring(0, max) : s ?? throw new ArgumentNullException(s);
}
}
答案 14 :(得分:4)
Kndly注意,截断字符串不仅仅意味着仅仅按指定的长度剪切字符串,而是必须注意不要分割字。
例如string:这是一个测试字符串。
我想在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());
}
答案 15 :(得分:4)
采取@CaffGeek并简化它:
public static string Truncate(this string value, int maxLength)
{
return string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(value.Length, maxLength));
}
答案 16 :(得分:3)
为什么不:
string NormalizeLength(string value, int maxLength)
{
//check String.IsNullOrEmpty(value) and act on it.
return value.PadRight(maxLength).Substring(0, maxLength);
}
即。在事件value.Length < maxLength
填充空格到最后或截断多余的。
答案 17 :(得分:3)
如果这里没有足够的答案,这里是我的:)
public static string Truncate(this string str,
int totalLength,
string truncationIndicator = "")
{
if (string.IsNullOrEmpty(str) || str.Length < totalLength)
return str;
return str.Substring(0, totalLength - truncationIndicator.Length)
+ truncationIndicator;
}
使用:
"I use it like this".Truncate(5,"~")
答案 18 :(得分:2)
为了(过度)复杂性,我将添加我的重载版本,该版本用maxLength参数的省略号替换最后3个字符。
public static string Truncate(this string value, int maxLength, bool replaceTruncatedCharWithEllipsis = false)
{
if (replaceTruncatedCharWithEllipsis && maxLength <= 3)
throw new ArgumentOutOfRangeException("maxLength",
"maxLength should be greater than three when replacing with an ellipsis.");
if (String.IsNullOrWhiteSpace(value))
return String.Empty;
if (replaceTruncatedCharWithEllipsis &&
value.Length > maxLength)
{
return value.Substring(0, maxLength - 3) + "...";
}
return value.Substring(0, Math.Min(value.Length, maxLength));
}
答案 19 :(得分:1)
这是一个vb.net解决方案,标记if(虽然丑陋)语句提高了性能,因为当string已经小于maxlength时我们不需要substring语句... 通过使它成为字符串的延伸,它很容易使用......
<System.Runtime.CompilerServices.Extension()> _
Public Function Truncate(String__1 As String, maxlength As Integer) As String
If Not String.IsNullOrEmpty(String__1) AndAlso String__1.Length > maxlength Then
Return String__1.Substring(0, maxlength)
Else
Return String__1
End If
End Function
答案 20 :(得分:1)
最近的C#中最简单的方法是:
string Trunc(string s, int len) => s?.Length > len ? s.Substring(0, len) : s;
对于较长的字符串,它返回截断的值;对于其他情况(包括空输入),它返回原始字符串,由?处理一元运算符。
答案 21 :(得分:1)
我知道已经有很多答案,但我的需要是保持字符串的开头和结尾不变,但将其缩短到最大长度。
public static string TruncateMiddle(string source)
{
if (String.IsNullOrWhiteSpace(source) || source.Length < 260)
return source;
return string.Format("{0}...{1}",
source.Substring(0, 235),
source.Substring(source.Length - 20));
}
这用于创建最大长度为260个字符的SharePoint URL。
我没有将长度作为参数,因为它是常数260.我也没有将第一个子串长度作为参数,因为我希望它在特定点处断开。最后,第二个子串是源的长度 - 20,因为我知道文件夹结构。
这可以很容易地适应您的特定需求。
答案 22 :(得分:1)
我更喜欢jpierson的答案,但我在这里看到的所有示例都没有处理无效的maxLength参数,例如maxLength&lt; 0
选择是在try / catch中处理错误,将maxLength参数min钳位到0,或者如果maxLength小于0则返回空字符串。
未优化的代码:
public string Truncate(this string value, int maximumLength)
{
if (string.IsNullOrEmpty(value) == true) { return value; }
if (maximumLen < 0) { return String.Empty; }
if (value.Length > maximumLength) { return value.Substring(0, maximumLength); }
return value;
}
答案 23 :(得分:1)
我知道这里已经有很多答案了,但这是我用过的那个,它处理空字符串和传入的长度为负的情况:
import scala.language.higherKinds
object Application extends App {
private val foo = new Foo
private val holder = new FooTypeHolder
private val client = new Client(holder)
client.showElementType(foo)
}
class Foo
trait TypeHolder {
type ElementType
}
class FooTypeHolder extends TypeHolder {
type ElementType = Foo
}
class Client[H <: TypeHolder](val holder: H) {
def showElementType(t: H#ElementType): Unit = {
println("show element type " + t.toString)
println(t.getClass)
}
}
答案 24 :(得分:0)
这是一个 C# 9 单行代码:
public static string Truncate(this string value, int maxLength) => value is null or "" || value.Length <= maxLength ? value : value[..maxLength];
答案 25 :(得分:0)
基于 this 和 this,这里有两个版本也适用于 negative values 的“最多”值。第一个不允许通过以 0 为上限来静默负值:
public static string Truncate(this string value, int maxLength)
{
return string.IsNullOrEmpty(value) ?
value :
value.Substring(0, Math.Max(0, Math.Min(value.Length, maxLength)));
}
这是一个循环:
private static int Mod(this int a, int n) => (((a %= n) < 0) ? n : 0) + a;
public static string Truncate(this string value, int maxLength)
{
return string.IsNullOrEmpty(value) ?
value :
value.Substring(0, maxLength.Mod(value.Length));
}
答案 26 :(得分:0)
所有其他答案都没有考虑到比 .NET 中字符串类型的子字符串性能更高的 Span
如果您还不知道有一个 System.Memory 版本(它为这样的情况提供了 Span、ReadOnlySpan、Memory 和 ReadOnlyMemory:
为此的简单实现如下:
public static string Truncate(this string value, int maxLength)
{
if (!string.IsNullOrEmpty(value) && value.Length > maxLength)
{
return value.AsSpan(0, maxLength).ToString(); /* Note the use of AsSpan instead of Substring. */
}
return value;
}
理论上可以使该方法返回 Span<char>
来避免使用 ToString()
的 Span<T>
成员分配新字符串。
BCL 本身在可能的情况下在内部使用 Span、ReadOnlySpan、Memory 和 ReadOnlyMemory 来避免问题并帮助优化代码,尤其是当您编译在编译时已知的数组并因此使用返回新的属性时up 数组作为 ReadOnlySpan<byte>
实际上在运行时优化了代码,因为这样 JIT 不会对数据调用 memcpy
而是使用它,因为它只返回一个跨度,因此是数据的窗口已经提前分配导致:
答案 27 :(得分:0)
流行的库 Humanizer 具有Truncate方法。要使用NuGet进行安装:
Install-Package Humanizer
答案 28 :(得分:0)
您可以创建一个Truncate
扩展方法,将最大长度与字符串长度进行比较,并在需要时调用Substring
。
如果您想要与Substring
类似的空处理行为,请不要包含空检查。这样,就像str.Substring(0, 10)
如果NullReferenceException
为null时抛出str
一样,str.Truncate(10)
也会抛出。{p>
public static class StringExtensions
{
public static string Truncate(this string value, int maxLength) =>
value.Length <= maxLength ? value : value.Substring(0, maxLength);
}
答案 29 :(得分:0)
TruncateString
public static string _TruncateString(string input, int charaterlimit)
{
int characterLimit = charaterlimit;
string output = input;
// Check if the string is longer than the allowed amount
// otherwise do nothing
if (output.Length > characterLimit && characterLimit > 0)
{
// cut the string down to the maximum number of characters
output = output.Substring(0, characterLimit);
// Check if the character right after the truncate point was a space
// if not, we are in the middle of a word and need to remove the rest of it
if (input.Substring(output.Length, 1) != " ")
{
int LastSpace = output.LastIndexOf(" ");
// if we found a space then, cut back to that space
if (LastSpace != -1)
{
output = output.Substring(0, LastSpace);
}
}
// Finally, add the "..."
output += "...";
}
return output;
}
答案 30 :(得分:0)
我的2美分,示例长度为30:
var truncatedInput = string.IsNullOrEmpty(input) ?
string.Empty :
input.Substring(0, Math.Min(input.Length, 30));
答案 31 :(得分:0)
除了上面讨论的可能性外,我想分享我的解决方案。 这是一个扩展方法,它允许null(返回string.Empty),并且还有第二个.Truncate(),将其与省略号一起使用。当心,它没有优化性能。
public static string Truncate(this string value, int maxLength) =>
(value ?? string.Empty).Substring(0, (value?.Length ?? 0) <= (maxLength < 0 ? 0 : maxLength) ? (value?.Length ?? 0) : (maxLength < 0 ? 0 : maxLength));
public static string Truncate(this string value, int maxLength, string ellipsis) =>
string.Concat(value.Truncate(maxLength - (((value?.Length ?? 0) > maxLength ? ellipsis : null)?.Length ?? 0)), ((value?.Length ?? 0) > maxLength ? ellipsis : null)).Truncate(maxLength);
答案 32 :(得分:-1)
我建议使用substring方法获得相同的有效功能。
// Gets first n characters.
string subString = inputString.Substring(0, n);
这样做的好处是可以让你从任何一边或甚至中间的某个地方拼接你的字符串,而无需编写其他方法。希望有所帮助:)
答案 33 :(得分:-1)
public static string Truncate( this string value, int maxLength )
{
if (string.IsNullOrEmpty(value)) { return value; }
return new string(value.Take(maxLength).ToArray());// use LINQ and be happy
}
答案 34 :(得分:-1)
我知道的.net中没有任何内容 - 这是我的版本添加了“......”:
public static string truncateString(string originalString, int length) {
if (string.IsNullOrEmpty(originalString)) {
return originalString;
}
if (originalString.Length > length) {
return originalString.Substring(0, length) + "...";
}
else {
return originalString;
}
}
答案 35 :(得分:-3)
截断字符串
public static string TruncateText(string strText, int intLength)
{
if (!(string.IsNullOrEmpty(strText)))
{
// split the text.
var words = strText.Split(' ');
// calculate the number of words
// based on the provided characters length
// use an average of 7.6 chars per word.
int wordLength = Convert.ToInt32(Math.Ceiling(intLength / 7.6));
// if the text is shorter than the length,
// display the text without changing it.
if (words.Length <= wordLength)
return strText.Trim();
// put together a shorter text
// based on the number of words
return string.Join(" ", words.Take(wordLength)) + " ...".Trim();
}
else
{
return "";
}
}
答案 36 :(得分:-4)
这是我经常使用的代码:
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();
}