2016-07-13 12 views
3

文字列は1文字で、長さは140文字に制限されています。 通常、私は自分のコードで140以上を取得します。 文字列は、次の形式で値が設定されます。Mxxxx xは任意の数値で、厳密な長さはありません。だから、私はM1を持っていても、私はM281を持つことができます。特殊文字を含む文字列の先頭140文字を取得

文字列が140文字より長い場合、最初は140文字を取りたいと思いますが、最後の文字列が半分になってしまった場合は、文字列に入れたくないのです。

まだ、私はいくつかのローカル変数に後半を保存する必要があります。

たとえば、これは文字列

"M5903, M6169, M6753, M619, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M669, M6753, M6919, M69, M6753, M6919, M6169, M63, M6919, M6169, M6753, M6919, M619, M653, M6919, M66, M6753, M19, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M619" 

であり、これは最初の140個の文字であると言うことができます言うことができます:

"M5903, M6169, M6753, M619, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M669, M6753, M6919, M69, M6753, M6919, M6169, M63, M69" 

最後の値がM6919だったが、それはM6919に分割されました。

最も効率的な言い方は次のとおりです。140より長い場合は分割するが、新しい文字列の最後の値を2つに分けた場合は、文字列の最初の部分から削除し、残りの文字列値に置きます。元の文字列。

おそらくこれを達成する方法はたくさんあります。私はifまたはswitch/caseループを使用して、最初の文字が 'M'でない場合、値が分割されていることを知るよりも、最初の文字列から削除する必要があります。このような

private static string CreateSettlmentStringsForUnstructuredField(string settlementsString) 
{ 
    string returnSettlementsString = settlementsString.Replace(", ", " "); 

    if (returnSettlementsString.Length > 140) 
    { 
     returnSettlementsString.Substring(0, 140); 
     /*if returnSettlementsString was spitted in two in a way 
      that last value was broken in two parts, take that value 
      out of returnSettlementStrings and put it in some new 
      string value with the other half of the string.*/ 
    } 
    return returnSettlementsString; 
} 
+0

なぜ文字列のリストを使用しないのですか? –

+0

@DmitriyKovalenkoよく私はそれのような文字列を取得します。私は確かに文字列のリストに変換することができますが、それから私はそれを再び刺し傷に変換しなければなりません、そして、私は長さなどのすべてのチェックを行う機能を行う必要があります。より複雑。 –

+0

最後のものを除いて各 'Mx'の直後にカンマがありますか? – dotctor

答えて

0

何か作業をする必要があります:

string test = "M5903, M6169, M6753, M619, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M669, M6753, M6919, M69, M6753, M6919, M6169, M63, M6919, M6169, M6753, M6919, M619, M653, M6919, M66, M6753, M19, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M619"; 

if (test.Length > 140) 
    if (test[140] != ',' && test[140] != ' ') // Last entry was split? 
     test = test.Substring(0, test.LastIndexOf(',', 139)); // Take up to but not including the last ',' 
    else 
     test = test.Substring(0, 139); 

Console.WriteLine(test); 
+2

'test = test.Substring(0、test.LastIndexOf( '、'))'末尾まで** ALL **文字を取ります。 – HimBromBeere

+0

@HimBromBeere OOps - 'LastIndexOf()'の '、139'パラメータが欠けていました。一定。 –

1

あなたの最善の策は、その後、「言葉」にあなたの文字列を分割文字列ビルダを使用してそれらを再構築することです。テストされていない生コードは次のようになります。

public IEnumerable<string> SplitSettlementStrings(string settlementsString) 
{ 
    var sb = new StringBuilder(); 
    foreach(var word in WordsFrom(settlementsString)) 
    { 
     var extraFragment = $"{word}, "; 
     if (sb.Length + extraFragment < 140) { 
     sb.Append(extraFragment); 
    } 
    else 
    { 
     // we'd overflow the 140 char limit, so return this fragment and continue; 
     yield return sb.ToString(); 
     sb = new StringBuilder(); 
    } 

    if (sb.Length > 0) { 
     // we may have content left in the string builder 
     yield return sb.ToString(); 
    } 
} 

このような方法で単語を分割する必要があります。

public IEnumerable<string> WordsFrom(string settlementsString) 
{ 
    // split on commas, then trim to remove whitespace; 
    return settlementsString.split(',').Select(x => x.Trim()).Where(x => x.Length > 0); 
} 

あなたはこのように全体を使用します。

var settlementStringsIn140CharLenghts = SplitSettlementStrings("M234, M456, M452 ...").ToArray() 

EDIT

古いSKOOLの.NETバージョンは次のようになります。

public ICollection<string> SplitSettlementStrings(string settlementsString) 
{ 
    List<string> results = new List<string>(); 
    StringBuilder sb = new StringBuilder(); 
    foreach(string word in WordsFrom(settlementsString)) 
    { 
     string extraFragment = word + ", "; 
     if (sb.Length + extraFragment < 140) { 
      sb.Append(extraFragment); 
     } 
    } 
    else 
    { 
     // we'd overflow the 140 char limit, so return this fragment and continue; 
     results.Add(sb.ToString()); 
     sb = new StringBuilder(); 
    } 

    if (sb.Length > 0) { 
     // we may have content left in the string builder 
     resuls.Add(sb.ToString()); 
    } 
} 

public ICollection<string> WordsFrom(string settlementsString) 
{ 
    // split on commas, then trim to remove whitespace; 
    string[] fragments = settlementsString.split(','); 
    List<string> result = new List<string>(); 
    foreach(string fragment in fragments) 
    { 
     var candidate = fragment.Trim(); 
     if (candidate.Length > 0) 
     { 
      result.Add(candidate); 
     } 
    } 
    return result; 
} 
+0

私は単語がC#6.0の機能だと思いますが、これはいくつかの古い古いバージョンです。多分3.5のように、私はアイデアが大好きだった:) @SteveCooper –

+0

ああ。次に、代わりにICollection を返し、リストの結果を集めるだけでそれを並べ替えることができます。 $ "{word}"ビットは "word +"に置き換えることができます。 " –

+0

old-skoolのバージョンが掲載されました。) –

0

私のテイク、ちょうど楽しみのために:

ここ
var ssplit = theString.Replace(", ", "#").Split('#');  
var sb = new StringBuilder(); 
for(int i = 0; i < ssplit.Length; i++) 
{ 
    if(sb.Length + ssplit[i].Length > 138) // 140 minus the ", " 
     break; 
    if(sb.Length > 0) sb.Append(", "); 
    sb.Append(ssplit[i]); 
} 

私はMxxxの部分に文字列を分割。(それは数の", "セパレータを含める必要があるため、または138)次の部分140をオーバーフローするまで、私はこれらの部分を反復

See it in action

+0

なぜ楽しいのですか? – Default

+0

私は面白い挑戦のように楽しく答えを出しました:-) – Jcl

2

このような何かが動作することができる:

string result; 
if (input.Length > 140) 
{ 
    result = new string(input.Take(140).ToArray()); 
    if (input[140] != ',') // will ensure that we don´t omit the last complete word if the 140eth character is a comma 
     result = result.Substring(0, result.LastIndexOf(',')); 
} 
else result = input; 

合計の長さが大きい場合は、最初の140文字がかかります。次に、カンマの最後のインデックスを検索し、までカンマで区切ります。

0

あなたがリストに文字列を分割したくない場合は、私は次のようなものだろう:

string myString = "M19, M42........"; 
string result; 
int index = 141; 

do 
{ 
    //Decrement index to reduce the substring size 
    index--; 

    //Make the result the new length substring 
    result = myString.Substring(0, index); 

}while (myString[index] != ','); //Check if our result contains a comma as the next char to check if we're at the end of an entry 

ですから、基本的にはちょうどで文字かどうかのチェック、140にあなたの元の文字列をsubstringingしているが位置141は、「クリーン」カットを示すカンマである。そうでない場合は、139で部分文字列を入力し、カンマなどで140をチェックします。

0

ここには解決策があります。文字列を141文字目から逆方向に処理します。おそらく

public static string Normalize(string input, int length) 
{ 
    var terminators = new[] { ',', ' ' }; 
    if (input.Length <= length + 1) 
     return input; 

    int i = length + 1; 
    while (!terminators.Contains(input[i]) && i > 0) 
     i = i - 1; 

    return input.Substring(0, i).TrimEnd(' ', ','); 
} 

Normalize(settlementsString, 140); 
0

ない新しい文字列のための継続的なメモリ割り当てのために最もパフォーマンスに敏感なソリューション、それはいくつかの種類の1時間の生データ入力のように聞こえるしかしありません。我々はもっとして140個の文字を持っている間だけ入力から「トークン」を削除するオプションがあります方法を指向

const string separator = ", "; 

while (input.Length > 140) 
{ 
    int delStartIndex = input.LastIndexOf(separator); 
    int delLength = input.Length - delStartIndex; 

    input = input.Remove(delStartIndex, delLength); 
} 

よりパフォーマンスが部分文字列のためにIEnumerable<string>またはstring[]のフォームを作成すること、及びそのカウントうそれらに参加する前に全長。この線に沿って何か:

const string separator = ", "; 
var splitInput = input.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); 

var length = splitInput[0].Length; 
var targetIndex = 1; 

for (targetIndex = 1; length <= 140; targetIndex++) 
    length += separator.Length + splitInput[targetIndex].Length; 

if (length > 140) 
    targetIndex--; 

var splitOutput = new string[targetIndex]; 
Array.Copy(splitInput, 0, splitOutput, 0, targetIndex); 

var output = string.Join(separator, splitOutput); 

私たちも、そのような素敵な拡張メソッド作ることができます。

public static class StringUtils 
{ 
    public static string TrimToLength(this string input, string separator, int targetLength) 
    { 
     var splitInput = input.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); 

     var length = splitInput[0].Length; 
     var targetIndex = 1; 

     for (targetIndex = 1; length <= targetLength; targetIndex++) 
      length += separator.Length + splitInput[targetIndex].Length; 

     if (length > targetLength) 
      targetIndex--; 

     var splitOutput = new string[targetIndex]; 
     Array.Copy(splitInput, 0, splitOutput, 0, targetIndex); 

     return string.Join(separator, splitOutput); 
    } 
} 

と同じようにそれを呼び出す:

input.TrimToLength(", ", 140); 

か:

input.TrimToLength(separator: ", ", targetLength:140); 
0

私はこれを使用します:

(コメント出力付き)試験サンプルコードを作業
static string FirstN(string s, int n = 140) 
{ 
    if (string.IsNullOrEmpty(s) || s.Length <= n) return s; 
    while (n > 0 && s[n] != ' ' && s[n] != ',') n--; 
    return s.Substring(0, n); 
} 

using System; 
namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static string FirstN(string s, int n = 140) 
     { 
      if (string.IsNullOrEmpty(s) || s.Length <= n) return s; 
      while (n > 0 && s[n] != ' ' && s[n] != ',') n--; 
      return s.Substring(0, n); 
     } 
     static void Main(string[] args) 
     { 
      var s = FirstN("M5903, M6169, M6753, M619, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M669, M6753, M6919, M69, M6753, M6919, M6169, M63, M6919, M6169, M6753, M6919, M619, M653, M6919, M66, M6753, M19, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M619"); 

      Console.WriteLine(s.Length); // 136 
      Console.WriteLine(s); //M5903, M6169, M6753, M619, M6169, M6753, M6919, M6169, M6753, M919, M6169, M6753, M6919, M6169, M6753, M6919, M6169, M6753, M919, M6169, 
     } 
    } 
} 

私はこのことができます願っています。

関連する問題