2012-03-29 131 views
49

我有一个包含二进制数字的字符串。如何在每个8位数后分隔字符串?在每N个字符处添加分隔符到字符串?

假设字符串为:

string x = "111111110000000011111111000000001111111100000000"; 

我希望每个8个字符后添加喜欢,(逗号)分隔。

输出应该是:

"11111111,00000000,11111111,00000000,11111111,00000000," 

然后我想将它发送到一个列表<>去年8月1日字符,然后前面的8个字符(除)等。

我该怎么做?

+1

你可以使用char或字节数组。 – 2012-03-29 19:27:55

+4

看到这个:http://stackoverflow.com/questions/3436398/convert-a-binary-string-representation-to-a-byte-array – Ryan 2012-03-29 19:28:22

+0

我可以做的第一件事情与string.Format()?如果不是如何? – 2012-03-29 19:31:25

回答

91
Regex.Replace(myString, ".{8}", "$0,"); 

如果你想八字符串数组,再下面是可能更容易:

Regex.Split(myString, "(?<=^(.{8})+)"); 

将只在点在那里的8个字符的多个它前面拆分字符串。

+1

+1哇,这是一个非常好的正则表达式学习! – dasblinkenlight 2012-03-29 19:41:01

+1

可能值得声称他们只是二进制“数字”,而不是任何字符:''[01] {8}“' – GalacticCowboy 2012-03-29 19:53:37

+3

那么,我希望他们知道他们扔进这个数据的是什么样的数据:) – Joey 2012-03-29 19:55:57

28

试试这个:

var s = "111111110000000011111111000000001111111100000000"; 
var list = Enumerable 
    .Range(0, s.Length/8) 
    .Select(i => s.Substring(i*8, 8)) 
    .ToList(); 
var res = string.Join(",", list); 
+1

这是一个很棒的解决方案。 – 2012-03-29 19:32:57

+0

是的确...谢谢@dasbinkeblight – 2012-03-29 19:36:35

+1

顺便说一句,你不需要'ToList()',因为'string.Join'具有[需要IEnumerable'的重载](http://msdn.microsoft.com/en-us /library/dd992421.aspx)(自.NET 4开始)。 – Joey 2012-03-29 19:57:18

2

如果我正确理解你的最后一个要求(这不是我清楚,如果你需要的中间用逗号分隔的字符串或没有),你可以这样做:

var enumerable = "111111110000000011111111000000001111111100000000".Batch(8).Reverse(); 

利用morelinq。使用LINQ

+0

如果只有'Batch'是标准的:(在任何情况下,这是知道更多的LINK的手 – 2012-03-29 19:40:21

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() 
    ); 
+0

此代码插入从右到左的分隔符。而不是从左到右 – 2016-03-27 21:22:31

2

还有一个正则表达式的方法:

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()); 
+0

我喜欢这种方法作为“件是可以理解的”,甚至如果它在.NET 3.5中需要更多一点fudge – 2012-03-29 19:48:40

+0

感谢您的补充:) - 我一直忘记检查框架兼容性。 – Alex 2012-03-29 19:50:07

+0

此代码删除characters.Separators将替换为字符串和字符串将丢失。 – 2016-03-27 21:18:12

1

...或老同学:

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

我称之为“Java”。不,谢谢:-) – 2012-03-29 19:48:04

+0

我称之为易读 - 但对每个人都是这样:D除了这里的正则表达式方法外,Linq方法在幕后正在做的事情是循环切入 - 更简单读书。我喜欢上面的批处理方法,对我来说这是一个新的方法:) – Wolf5370 2012-03-29 19:53:22

+0

虽然'length'不是'System.String'的成员,它甚至不会编译。 – Joey 2014-03-14 08:16:17

2

丑陋但不太垃圾:

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

这是更快而不复制阵列(这个版本的插入空间,每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); 
} 
+0

我不明白这一点。 valueField一个double?你将输入字符串转换为double,以便在函数中使用它,然后将其重新转换为字符串和charArray?你介意对代码进行一些评论吗? – Joze 2015-05-21 09:04:04

+0

我没有输入字符串。我只有一个double值,这就是为什么'valueFiled'是double的原因。如果你有字符串值,那么你可以创建'valueFiled'字符串并将第一行改为'char [] ins = valueField.ToCharArray();'。 – 2015-05-27 13:45:23

0

有点迟到了,但这里有一个简单的LINQ表达式打破输入字符串x成另一个字符串sep分离的n组:

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方法中,通过使用String()构造函数将n字符的每个组转换回字符串,该构造函数采用chars的数组。
  • Select的结果现在是IEnumerable<string>,它被传递到String.Join以交织sep字符串,就像任何其他示例一样。
-1

我比后期多与我的答案,但你可以用这一个:

static string PutLineBreak(string str, int split) 
    { 
     for (int a = 1; a <= str.Length; a++) 
     { 
      if (a % split == 0) 
       str = str.Insert(a, "\n"); 
     } 

     return str; 
    }