web-dev-qa-db-ja.com

.NET文字列を切り捨てる方法

文字列の長さが与えられた値より長くならないように文字列を切り詰めたいのですが。データベーステーブルに書き込んでいるのですが、書き込む値が列のデータ型の制約を満たすようにしたいのです。

例えば、私が以下を書くことができればそれはいいでしょう:

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

356
Steve Guidi

stringに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);
542
LBushkin

あるいは、三項演算子の代わりに、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));
    }
}
111
CaffGeek

私はそれが他の人によって触れられてきたすべてのケースをカバーしていて、まだ読みやすい簡潔な方法でそうすると信じているので、私は私の実装を投入すると考えました。

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 キーワードを使用して拡張メソッドとして使用するメソッドを開きます。

36
jpierson

.NET 4.0では、Takeメソッドを使用できます。

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

効率試験はしていません!

30
Dylan Nicholson

あなたはLINQを使うことができます...それは文字列の長さをチェックする必要性を排除します。確かに最も効率的ではないかもしれませんが、それは楽しいです。

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

または

string result = new string(value.Take(maxLength).ToArray());
27
tames

パフォーマンステストは楽しいので、( 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担当者で、1回あたり0.00010557ミリ秒]
  • concat10 45495チック経過(4.5495ミリ秒)[10K担当者で、0.00045495ミリ秒あたり]
  • newstring10 72535チックが経過しました(7.2535ミリ秒)[10K担当者で、1回あたり0.00072535ミリ秒]

後期

  • truncate44 8835ティック経過(0.8835ミリ秒)[10K担当者で、8.835E-05ミリ秒]
  • stringbuilder44 13106ティック経過(1.3106ミリ秒)[10K担当者で、0.00013106ミリ秒]
  • smart-trunc44 14821ティック経過(1.4821ミリ秒)[10K担当者で、1回あたり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担当者で、1回あたり0.00013314ミリ秒]
  • newstring64 177481チックが経過しました(17.7481ミリ秒)[10K担当者で、0.00177481ミリ秒]
  • concat64 241601ティック経過(24.1601ミリ秒)[10K担当者で、0.00241601ミリ秒]
23
drzaus

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

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

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

12
Darren

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

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

しかし、C#アプリでは、おそらくMicrosoft.VisualBasic.dllへの依存よりも自分自身でロールバックするほうがよいでしょう。その主な理由は後方互換性です。

11
Joe

私はこのように一列に並べて採掘しました

value = value.Length > 1000 ? value.Substring(0, 1000) : value;
10
SeanMC

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

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

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

5
nologo

C#6のNull伝播演算子を使った同様の変種

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

注意してください、ここではvalueがnullであるかどうかを確認しています。

5
Jamie Rees

@CaffGeekを使用してそれを単純化する:

public static string Truncate(this string value, int maxLength)
    {
        return string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(value.Length, maxLength));
    }
4
Edwin Beltran

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

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

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());
} 
4
Sen K. Mathew

C#文字列に対する2016年の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"
4
Tobias Schiele

別の解決策:

return input.Substring(0, Math.Min(input.Length, maxLength));
4

何故なの:

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

つまり、value.Length < maxLengthの場合は最後までスペースを埋めるか、余分な部分を切り捨てます。

3
Sri

念のために、ここに十分な答えがない、私のものはここにあります:)

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,"~")
3
K. R.

(過度の)複雑さのために、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)); 
}
2
SoftDev

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

  var truncatedInput = string.IsNullOrEmpty(input) ? 
      string.Empty : 
      input.Substring(0, Math.Min(input.Length, 30));
1
Ognyan Dimitrov

私はすでにたくさんの答えがあることを知っています、しかし私の必要性は弦の始めと終わりを無傷のままにしてそれを最大の長さ以下に短くすることでした。

    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なので、長さをパラメータにしませんでした。最初の部分文字列の長さをパラメータにしませんでした。特定の時点で分割したいからです。最後に、2番目のサブストリングはソースの長さです - 私はフォルダー構造を知っているので20です。

これは簡単にあなたの特定のニーズに適応させることができます。

1
Paul Haan

私は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;
}
1
deegee

これはvb.netの解決策です。stringがmaxlengthよりも小さい場合は、if(醜いですが)substringステートメントは必要ないのでパフォーマンスが向上することを確認してください。それをstringへの拡張として使用するのは簡単です。 ..

 <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
1
Jeroen Bom

ここにはすでにたくさんの答えがあることを知っていますが、これは私が使ったことのあるもので、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);
}
1
Ed B

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;
}
0
Sud

上記の可能性に加えて、私は自分の解決策を共有したいと思います。これは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);
0