每N个字符在字符串中添加分隔符?


76

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

假设字符串是:

string x = "111111110000000011111111000000001111111100000000";

我想在每8个字符后添加一个分隔符,例如,(逗号)。

输出应为:

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

然后,我想将其发送到list <>最后8个字符,然后再发送到前面的8个字符(,除外),依此类推。

我怎样才能做到这一点?


1
您可以使用char或字节数组。
AliRızaAdıyahşi


我可以用string.Format()做第一件事吗?
Abdur Ra​​him 2012年

Answers:


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

如果您想要一个由八个字符组成的字符串数组,那么以下操作可能会更容易:

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

这只会在字符串前面八个字符的倍数处分割字符串。


1
可能值得断言它们只是二进制“数字”,而不是任何字符: "[01]{8}"
GalacticCowboy 2012年

3
好吧,我希望他们知道他们要放入什么样的数据:)
Joey 2012年

您能向我解释“ $ 0”部分吗?我不太确定应该如何读取/评估该表达式。
scottmgerstl

1
在替换部分$0是指整个匹配项($1是第一个捕获组,等等)。您也可以使用$&
乔伊

17
虽然请求确实要求结尾逗号,但如果开发人员不希望结尾逗号,则他们可以将RegEx模式更改为“。{8}(?!$)”,该模式使用否定的前瞻性以确保它与字符串末尾八个字符。
乔什·里昂

43

试试这个:

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

是的,确实是……感谢@dasbinkeblight
Abdur Ra​​him

1
ToList()顺便说一句,您不需要,因为string.Join一个重载需要IEnumerable(从.NET 4开始)。
乔伊(Joey)

1
@Joey我知道,但是我最初误解了这个问题。我阅读了OP所说的“然后我想将其发送到列表<>”部分,并张贴了一个答案,ToList()没有string.Join一行。然后,我重新阅读了该问题,添加res = ...并保存了该问题,但我忘记删除了ToList()
谢尔盖·卡利尼琴科

1
制作了扩展方法后出现了一个问题。如果字符串较短,则间隔。如果(s.Length <interval)返回s; 但除此之外,效果很好。
智者酸奶

此方法剪切字符串的长度。如果s字符串中还包含7个字符,则不会返回这些字符。
莫特

3

...或旧学校:

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

1
我认为它很容易阅读-但对于每个人来说都是很容易的:D除了这里的Regex方法,这是Linq方法在幕后所做的-遍历和切碎-更加容易阅读。我确实喜欢上面的Batch方法,这对我来说是一个新方法:)
Wolf5370,2012年

但是,它甚至不会编译,因为length它不是的成员System.String
2014年

3

丑陋但垃圾少:

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

3

还有另一种正则表达式方法:

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

我喜欢这种方法,因为“片段是可以理解的”,即使在.NET 3.5中需要花更多的时间

感谢您的添加:)-我一直忘记检查框架兼容性。
亚历克斯(Alex)

1
此代码删除字符。分隔符将替换为字符串,而字符串将丢失。
Mohsen Tavoosiمحسنطاوسی16年

2

如果我正确理解了您的最后一个要求(不清楚您是否需要中间用逗号分隔的字符串),可以执行以下操作:

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

通过利用morelinq


如果仅Batch是标准:(在任何情况下,它的手了解morelinq。

1

使用LINQ的一种方法:

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

此代码插入分隔符从右到left.Instead的左到右
穆赫辛Tavoosiمحسنطاوسی

1

这也是我的两分钱。使用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, ',');

如果str为null或短于chunk_len,则此方法将失败
Greg

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

我不明白 valueField是两倍?您将输入字符串转换为double以便在函数中使用它,然后将其重新转换为string和charArray?您介意将代码注释一下吗?
Joze

我没有输入字符串。我只是有一个双重价值,这就是为什么valueFiled是双重的。如果您具有字符串值,则可以制作valueFiled字符串并将第一行更改为char[] ins = valueField.ToCharArray();
MateuszPuwałowski15年

0

聚会晚了一点,但这是一个简化的LINQ表达式xn它将输入字符串分成由另一个字符串分隔的组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)将字符分组IEnumerableIEnumerable-外部分组中的每个条目都包含一个内部n字符组。
  • Select方法内部n,使用String()采用数组的构造函数将每组字符转回字符串chars
  • 现在的结果Select是,就像其他任何示例一样IEnumerable<string>,该结果将被传递到String.Join交错sep字符串中。

0

我使用PatternMatcher通过以下方式做到了:

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表示在这些字符之间插入字符串。例如,逗号(,),开始(*),哈希(#)。

interval 指示要在哪个间隔添加插入字符。

input表示输入字符串。检查结果部分。检查结果部分;在这里,我在第4个字符处添加了插入。

结果:

输入/输出 1234XXXXXXXX5678输入/输出: 1234 XXXX XXXX 5678

I / P: 1234567812345678 O / P: 1234 5678 1234 5678

I / P: ABCDEFGHIJKLMNOP O / P: ABCD EFGH IJKL MNOP

希望这可以帮助。


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

-1

对于每1个字符,您可以执行以下操作:

string.Join(".", "1234".ToArray()) //result: 1.2.3.4
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.