2進数を含む文字列があります。 8桁ごとに文字列を区切る方法は?
文字列が次のとおりだとします:
string x = "111111110000000011111111000000001111111100000000";
8文字ごとに、(コンマ)のような区切り文字を追加したい。
出力は次のようになります。
"11111111,00000000,11111111,00000000,11111111,00000000,"
次に、最後に8文字目をリスト<>に送り、次に前の8文字(、を除く)などを送信します。
これどうやってするの?
Regex.Replace(myString, ".{8}", "$0,");
8文字の文字列の配列が必要な場合は、おそらく次の方が簡単です。
Regex.Split(myString, "(?<=^(.{8})+)");
これは、8文字の倍数が先行するポイントでのみ文字列を分割します。
これを試して:
var s = "111111110000000011111111000000001111111100000000";
var list = Enumerable
.Range(0, s.Length/8)
.Select(i => s.Substring(i*8, 8))
.ToList();
var res = string.Join(",", list);
別の正規表現アプローチがあります:
var str = "111111110000000011111111000000001111111100000000";
# for .NET 4
var res = String.Join(",",Regex.Matches(str, @"\d{8}").Cast<Match>());
# for .NET 3.5
var res = String.Join(",", Regex.Matches(str, @"\d{8}")
.OfType<Match>()
.Select(m => m.Value).ToArray());
Glyいがゴミが少ない:
private string InsertStrings(string s, int insertEvery, char insert)
{
char[] ins = s.ToCharArray();
int length = s.Length + (s.Length / insertEvery);
if (ins.Length % insertEvery == 0)
{
length--;
}
var outs = new char[length];
long di = 0;
long si = 0;
while (si < s.Length - insertEvery)
{
Array.Copy(ins, si, outs, di, insertEvery);
si += insertEvery;
di += insertEvery;
outs[di] = insert;
di ++;
}
Array.Copy(ins, si, outs, di, ins.Length - si);
return new string(outs);
}
文字列のオーバーロード:
private string InsertStrings(string s, int insertEvery, string insert)
{
char[] ins = s.ToCharArray();
char[] inserts = insert.ToCharArray();
int insertLength = inserts.Length;
int length = s.Length + (s.Length / insertEvery) * insert.Length;
if (ins.Length % insertEvery == 0)
{
length -= insert.Length;
}
var outs = new char[length];
long di = 0;
long si = 0;
while (si < s.Length - insertEvery)
{
Array.Copy(ins, si, outs, di, insertEvery);
si += insertEvery;
di += insertEvery;
Array.Copy(inserts, 0, outs, di, insertLength);
di += insertLength;
}
Array.Copy(ins, si, outs, di, ins.Length - si);
return new string(outs);
}
...または古い学校:
public static List<string> splitter(string in, out string csv)
{
if (in.length % 8 != 0) throw new ArgumentException("in");
var lst = new List<string>(in/8);
for (int i=0; i < in.length / 8; i++) lst.Add(in.Substring(i*8,8));
csv = string.Join(",", lst); //This we want in input order (I believe)
lst.Reverse(); //As we want list in reverse order (I believe)
return lst;
}
最後の要件を正しく理解している場合(中間のコンマ区切り文字列が必要かどうかは明確ではありません)、これを行うことができます:
var enumerable = "111111110000000011111111000000001111111100000000".Batch(8).Reverse();
morelinq を利用することにより。
ここに私の2セントも。 StringBuilderを使用した実装:
public static string AddChunkSeparator (string str, int chunk_len, char separator)
{
if (str == null || str.Length < chunk_len) {
return str;
}
StringBuilder builder = new StringBuilder();
for (var index = 0; index < str.Length; index += chunk_len) {
builder.Append(str, index, chunk_len);
builder.Append(separator);
}
return builder.ToString();
}
次のように呼び出すことができます。
string data = "111111110000000011111111000000001111111100000000";
string output = AddChunkSeparator(data, 8, ',');
LINQを使用する1つの方法:
string data = "111111110000000011111111000000001111111100000000";
const int separateOnLength = 8;
string separated = new string(
data.Select((x,i) => i > 0 && i % separateOnLength == 0 ? new [] { ',', x } : new [] { x })
.SelectMany(x => x)
.ToArray()
);
Pattern&Matcherを次のように使用しました:
fun addAnyCharacter(input: String, insertion: String, interval: Int): String {
val pattern = Pattern.compile("(.{$interval})", Pattern.DOTALL)
val matcher = pattern.matcher(input)
return matcher.replaceAll("$1$insertion")
}
どこ:
input
は入力文字列を示します。結果セクションを確認してください。
insertion
は、これらの文字の間に文字列を挿入することを示します。たとえば、コンマ(、)、start(*)、hash(#)。
interval
は、挿入文字を追加する間隔を示します。
input
は入力文字列を示します。結果セクションを確認してください。結果セクションを確認してください。ここでは、4番目の文字ごとに挿入を追加しました。
I/P: 1234XXXXXXXX5678 O/P: 1234 XXXX XXXX 5678
I/P: 1234567812345678 O/P: 1234 5678 1234 5678
I/P: ABCDEFGHIJKLMNOP O/P: ABCD EFGH IJKL MNOP
お役に立てれば。
これは配列をコピーしなくてもはるかに高速です(このバージョンでは3桁ごとにスペースが挿入されますが、必要に応じて調整できます)
public string GetString(double valueField)
{
char[] ins = valueField.ToString().ToCharArray();
int length = ins.Length + (ins.Length / 3);
if (ins.Length % 3 == 0)
{
length--;
}
char[] outs = new char[length];
int i = length - 1;
int j = ins.Length - 1;
int k = 0;
do
{
if (k == 3)
{
outs[i--] = ' ';
k = 0;
}
else
{
outs[i--] = ins[j--];
k++;
}
}
while (i >= 0);
return new string(outs);
}
1文字ごとに、この1行を実行できます。
string.Join(".", "1234".ToArray()) //result: 1.2.3.4
パーティーに少し遅れましたが、入力文字列を分割するための簡略化されたLINQ式がありますx
のグループに別の文字列で区切られたn
sep
:
_string sep = ",";
int n = 8;
string result = String.Join(sep, x.InSetsOf(n).Select(g => new String(g.ToArray())));
_
ここで何が起こっているかの簡単な要約:
x
は_IEnumberable<char>
_として扱われ、InSetsOf
拡張メソッドが入っています。InSetsOf(n)
は、IEnumerable
のIEnumerable
に文字をグループ化します。外部グループの各エントリには、n
文字の内部グループが含まれます。Select
メソッド内では、n
の配列を受け取るString()
コンストラクターを使用して、chars
文字の各グループが文字列に戻されます。Select
の結果は_IEnumerable<string>
_になり、他の例と同様にsep
文字列をインターリーブするために_String.Join
_に渡されます。