470

文字列の長さが指定された値より長くならないように文字列を切り捨てたいと思います。データベーステーブルに書き込んでいますが、書き込んだ値が列のデータ型の制約を満たしていることを確認したいと思います。

たとえば、次のように書くことができればいいのですが。

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はどこにありますか?ありますか?

4

37 に答える 37

741

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);
2021-09-17サフィックスとc#8null許容参照型を使用した代替。
public static class StringExt
{
    public static string? Truncate(this string? value, int maxLength, string truncationSuffix = "…&quot;)
    {
        return value?.Length > maxLength
            ? value.Substring(0, maxLength) + truncationSuffix
            : value;
    }
}

書くには:

"abc".Truncate(2);          // "ab…&quot;
"abc".Truncate(3);          // "abc"
((string)null).Truncate(3); // null
于 2010-05-05T20:52:53.393 に答える
158

または、三項演算子の代わりに、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));
    }
}
于 2010-05-05T20:57:36.347 に答える
48

他の人が触れたすべてのケースをカバーし、まだ読みやすい簡潔な方法でそれを行うと信じているので、私は自分の実装を投入すると思いました。

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

    return value;
}

このソリューションは、主にRayのソリューションに基づいて構築されており、 LBushkinがソリューションで行っているように、 thisキーワードを使用することにより、拡張メソッドとして使用するためのメソッドを開きます。

于 2011-05-03T14:20:13.910 に答える
46

パフォーマンステストは楽しいので:( 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();

この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ティック経過(0.8835ミリ秒)[10K担当者、8.835E-05ミリ秒あたり]
  • stringbuilder44 13106ティック経過(1.3106ミリ秒)[10K担当者、0.00013106ミリ秒あたり]
  • smart-trunc44 14821ティック経過(1.4821ミリ秒)[10K担当者、0.00014821ミリ秒あたり]
  • newstring44 144324ティック経過(14.4324ミリ秒)[10K担当者、0.00144324ミリ秒あたり]
  • concat44 174610ティック経過(17​​.461ミリ秒)[10K担当者、0.0017461ミリ秒あたり]

長すぎる

  • smart-trunc64 6944ティック経過(0.6944ミリ秒)[10K担当者、6.944E-05ミリ秒あたり]
  • truncate64 7686ティック経過(0.7686ミリ秒)[10K担当者、7.686E-05ミリ秒あたり]
  • stringbuilder64 13314ティック経過(1.3314ミリ秒)[10K担当者、0.00013314ミリ秒あたり]
  • newstring64 177481ティック経過(17​​.7481ミリ秒)[10K担当者、0.00177481ミリ秒あたり]
  • concat64 241601ティック経過(24.1601ミリ秒)[10K担当者、0.00241601ミリ秒あたり]
于 2016-12-01T19:00:40.517 に答える
42

Take.NET 4.0では、次の方法を使用できます。

string.Concat(myString.Take(maxLength));

効率はテストされていません!

于 2013-12-06T04:08:27.637 に答える
30

LINQを使用できます...文字列の長さをチェックする必要がなくなります。確かに最も効率的ではないかもしれませんが、それは楽しいです。

string result = string.Join("", value.Take(maxLength)); // .NET 4 Join

また

string result = new string(value.Take(maxLength).ToArray());
于 2010-05-05T20:59:56.273 に答える
29

別の解決策:

return input.Substring(0, Math.Min(input.Length, maxLength));
于 2019-02-02T09:09:15.913 に答える
22

私はこのような一行で私のものをしました

value = value.Length > 1000 ? value.Substring(0, 1000) : value;
于 2017-05-23T16:30:48.133 に答える
17

.NET Frameworkには、次のような文字列を切り捨てるためのAPIがあります。

Microsoft.VisualBasic.Strings.Left(string, int);

ただし、C#アプリでは、Microsoft.VisualBasic.dllに依存するよりも、独自のロールを使用する方がよいでしょう。Microsoft.VisualBasic.dllの主な存在理由は、下位互換性です。

于 2012-11-08T14:46:43.987 に答える
16

まだ誰もこれを投稿していないようです:

public static class StringExt
{
    public static string Truncate(this string s, int maxLength)
    {
        return s != null && s.Length > maxLength ? s.Substring(0, maxLength) : s;
    }
}

&&演算子を使用すると、受け入れられた回答よりもわずかに良くなります。

于 2014-10-03T08:38:23.597 に答える
7

私はこれが古い質問であることを知っていますが、ここに素晴らしい解決策があります:

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);

戻り値:こんにちは...

于 2014-02-27T22:16:37.677 に答える
7

C#8では、新しい範囲機能を使用できます...

value = value[..Math.Min(30, value.Length)];
于 2020-01-08T05:21:26.390 に答える
6

2016年には、C#文字列のTruncateメソッドはまだありません。しかし-C#6.0構文の使用:

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); 
  }
}

それは魅力のように機能します:

"Truncate me".Truncate(8);
Result: "Truncate"
于 2016-10-28T14:30:48.783 に答える
5

なぜだめですか:

string NormalizeLength(string value, int maxLength)
{
    //check String.IsNullOrEmpty(value) and act on it. 
    return value.PadRight(maxLength).Substring(0, maxLength);
}

つまり、イベントvalue.Length < maxLengthパッドで最後までスペースを空けるか、余分な部分を切り捨てます。

于 2013-08-29T15:47:43.140 に答える
5

C#6のNull伝播演算子を使用した同様のバリアント

public static string Truncate(this string value, int maxLength)
{
    return value?.Length <= maxLength ? value : value?.Substring(0, maxLength);
}

valueここでは、基本的にnullかどうかを2回チェックしていることに注意してください。

于 2016-04-19T14:19:59.790 に答える
4

@CaffGeekを取り、それを単純化する:

public static string Truncate(this string value, int maxLength)
    {
        return string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(value.Length, maxLength));
    }
于 2013-03-26T18:56:39.837 に答える
4

文字列を切り捨てるということは、単に指定された長さの文字列を切り取るだけではなく、単語を分割しないように注意する必要があることに注意してください。

例:文字列:これはテスト文字列です。

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());
} 
于 2013-05-29T04:55:38.987 に答える
4

最近のC#で最も簡単な方法は次のとおりです。

string Trunc(string s, int len) => s?.Length > len ? s.Substring(0, len) : s;

長い文字列の場合は切り捨てられた値を返し、他の場合(null入力を含む)の場合は元の文字列を返します。これは?によって処理されます。単項演算子。

于 2020-12-08T16:27:37.993 に答える
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,"~")
于 2014-11-26T18:09:56.547 に答える
3

ここにはすでにたくさんの答えがあることを私は知っていますが、これは私が行ったものであり、null文字列と渡された長さが負の状況の両方を処理します:

public static string Truncate(this string s, int length)
{
    return string.IsNullOrEmpty(s) || s.Length <= length ? s 
        : length <= 0 ? string.Empty 
        : s.Substring(0, length);
}
于 2018-03-14T11:11:33.647 に答える
3

例の長さが30の私の2セント:

  var truncatedInput = string.IsNullOrEmpty(input) ? 
      string.Empty : 
      input.Substring(0, Math.Min(input.Length, 30));
于 2019-07-04T07:42:19.050 に答える
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)); 
}
于 2014-01-09T16:26:26.127 に答える
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;
  }
}
于 2010-05-05T20:57:13.923 に答える
1

私はjpiersonの答えを好みますが、ここで見ることができる例はどれも、maxLength <0の場合など、無効なmaxLengthパラメーターを処理していません。

選択肢は、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;
}
于 2013-03-23T19:36:34.220 に答える
1

これがvb.netソリューションです。文字列がすでにmaxlengthよりも小さい場合、サブ文字列ステートメントは必要ないため、if(醜いですが)ステートメントがパフォーマンスを向上させることを示してください...文字列の拡張にすることで、使いやすくなります。 ..

 <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
于 2015-01-20T08:33:43.557 に答える
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文字のSharePointURLを作成するためのものです。

長さは定数260であるため、パラメーターにしませんでした。また、最初の部分文字列の長さを特定のポイントで分割したいので、パラメーターにしませんでした。最後に、2番目のサブストリングは、ソースの長さです。フォルダー構造がわかっているので、20です。

これは、特定のニーズに簡単に適合させることができます。

于 2016-11-16T16:37:34.960 に答える
1

人気のあるライブラリHumanizerにはTruncateメソッドがあります。NuGetを使用してインストールするには:

Install-Package Humanizer
于 2020-08-19T20:01:26.027 に答える
1

これがC#9ワンライナーです:

public static string Truncate(this string value, int maxLength) => value is null or "" || value.Length <= maxLength ? value : value[..maxLength];
于 2021-03-10T15:48:33.670 に答える
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;
}
于 2016-01-25T09:17:24.850 に答える
0

上記の可能性に加えて、私は自分の解決策を共有したいと思います。これは、null(string.Emptyを返す)を許可する拡張メソッドであり、省略記号で使用するための2番目の.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);
于 2018-11-15T12:45:47.187 に答える
0

Truncate文字列の長さに対して最大長を比較し、必要に応じて呼び出す拡張メソッドを作成できますSubstring

と同様のnull処理動作が必要な場合Substringは、nullチェックを含めないでください。そうすれば、 ifがnullをstr.Substring(0, 10)スローするのと同じように、もnullになります。NullReferenceExceptionstrstr.Truncate(10)

public static class StringExtensions
{
    public static string Truncate(this string value, int maxLength) =>
        value.Length <= maxLength ? value : value.Substring(0, maxLength); 
}
于 2020-08-19T19:56:25.667 に答える
0

これとこれに基づいて、「最大」値のの値に対しても機能する2つのバージョンがあります。この最初のものは、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));
}
于 2020-12-23T22:48:55.390 に答える
0

他のすべての回答は、.NETの文字列型の部分文字列よりもパフォーマンスが高いスパンを考慮していません。

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を内部的に使用します。特に、コンパイル時に既知の配列をコンパイルする場合は、その新しい配列を次のように返すプロパティを使用します。実際には、ReadOnlySpan<byte>実行時にコードを最適化します。JITはmemcpyデータを呼び出さず、代わりにそれを使用します。これは、スパンを返すだけであり、事前に割り当てられているデータへのウィンドウであるため、次のようになります。

  1. より少ない割り当て。
  2. 割り当てに費やす時間が短縮されます。
  3. コード全体の使用が速くなります。
于 2021-04-27T09:37:52.483 に答える
-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
    }
于 2013-05-17T20:19:21.900 に答える
-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 "";
        }            
    }
于 2016-05-27T13:39:11.113 に答える
-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();
        }
于 2014-09-19T23:52:34.953 に答える
-4

同じ効果的な機能のために部分文字列メソッドを使用することをお勧めします。

    // Gets first n characters.
    string subString = inputString.Substring(0, n);

これには、追加のメソッドを記述せずに、文字列をどちらかの側から、または中央のどこかからスプライスできるという利点があります。お役に立てば幸いです:)

追加の参照:https ://www.dotnetperls.com/substring

于 2018-02-16T19:20:03.097 に答える