每 N 个字符向字符串添加分隔符

本文关键字:字符串 添加 分隔符 字符 | 更新日期: 2023-09-27 18:29:31

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

假设字符串为:

string x = "111111110000000011111111000000001111111100000000";

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

输出应为:

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

然后我想把它发送到一个列表<>最后 8 个字符 1st 然后是前 8 个字符(除了 ,(依此类推。

我该怎么做?

每 N 个字符向字符串添加分隔符

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

如果你想要一个八个字符的字符串数组,那么以下内容可能更容易:

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

这将仅在八个字符的倍数前面的点拆分字符串。

试试这个:

var s = "111111110000000011111111000000001111111100000000";
var list = Enumerable
    .Range(0, s.Length/8)
    .Select(i => s.Substring(i*8, 8));
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());

...或老派:

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

丑陋但垃圾较少:

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

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

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

通过利用莫林克。

我的两分钱也是。使用 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 的一种方式:

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(*(、哈希 (#(。

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

希望这有帮助。

.Net 6 开始,您可以简单地使用 IEnumerable.Chunk 方法(该方法将序列的元素拆分为块(,然后使用 String.Join 重新连接这些块。

var text = "...";
string.Join(',', text.Chunk(size: 6).Select(x => new string(x)));

这在不复制数组的情况下要快得多(此版本每 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 个字符,您可以执行以下单行操作:

string.Join(".", "1234".ToArray()) //result: 1.2.3.4

如果您打算创建自己的函数来实现此目的,而无需使用正则表达式或模式匹配方法,则可以创建如下的简单函数:

String formatString(String key, String seperator, int afterEvery){
        String formattedKey = "";
        for(int i=0; i<key.length(); i++){
            formattedKey += key.substring(i,i+1);
            if((i+1)%afterEvery==0)
                formattedKey += seperator;
        }
        if(formattedKey.endsWith("-"))
            formattedKey = formattedKey.substring(0,formattedKey.length()-1);
        return formattedKey;
    }

像这样称呼飞蛾

formatString("ABCDEFGHIJKLMNOPQRST", "-", 4)

将导致返回字符串如下

ABCD-EFGH-IJKL-MNOP-QRST
派对

有点晚了,但这里有一个简化的 LINQ 表达式,用于将输入字符串x分成由另一个字符串分隔的nsep

string sep = ",";
int n = 8;
string result = String.Join(sep, x.InSetsOf(n).Select(g => new String(g.ToArray())));

这里发生的事情的简要介绍:

  • x被视为IEnumerable<char>,这就是InSetsOf扩展方法的用武之地。
  • InSetsOf(n)字符分组到IEnumerable IEnumerable -- 外部分组中的每个条目都包含一个由n字符组成的内部组。
  • Select 方法中,每组 n 字符都通过使用采用chars数组的 String() 构造函数重新转换为字符串。
  • Select的结果现在是一个IEnumerable<string>,它被传递到String.Join以交错sep字符串,就像任何其他示例一样。

这些答案中的大多数都有效,但在处理表情符号支持时会遇到问题。由于这些字符可能看起来像一个 ,但在引擎盖下它们实际上是:+ ++ , 如果我们拆分不正确,表情符号最终可能会被分解。

我写了一组快速测试,如下所示:

    [InlineData(null, 1, "")]
    [InlineData(null, 2, "")]
    [InlineData("    ", 3, "")]
    [InlineData("aaaaa", 1, "a a a a a")]
    [InlineData("aaaaa", 2, "aa aa a")]
    [InlineData("aaaaa", 3, "aaa aa")]
    [InlineData("aaaaa", 4, "aaaa a")]
    [InlineData("aaaaa", 6, "aaaaa")]
    [InlineData("aaaaa", 30, "aaaaa")]
    [InlineData("          ", 4, "           ")]
    [InlineData("    a    ", 4, "    a     ")]
    [InlineData("aaa    ", 4, "aaa     ")]
    [InlineData("aaa  ‍  ‍  ‍    ", 4, "aaa  ‍  ‍  ‍     ")]
    public void TestAddSpaces(string? value, int numOfCharsBetweenSpaces, string expected)
    {
        ...Add Space Code Here
        Assert.Equal(expected, actual);
    }

仅根据 string.length 插入每个 X 个字符的空格,结果如下,因为表情符号在中间被拆分:

Assert.Equal() Failure
                  ↓ (pos 4)
    Expected: aaa     
    Actual:   aaa� �  
                  ↑ (pos 4)
Assert.Equal() Failure
                  ↓ (pos 4)
    Expected: aaa  ‍  ‍  ‍     
    Actual:   aaa� �‍   ‍  ‍     

使用这个堆栈溢出问题中的 .Net 5+ 答案:如何在 C# 中将 Unicode 字符串拆分为多个 Unicode 字符? 在拆分字符串元素时,我们能够可靠地以用户期望的方式在字符串中插入间距。

    public static string AddSpacesSplitText(this string? value, int numOfCharsBetweenSpaces)
    {
        if (string.IsNullOrWhiteSpace(value))
            return string.Empty;
        var elements = SplitIntoTextElements(value);
        string retval = string.Empty;
        for (int i = 0; i <= elements.Length; i += numOfCharsBetweenSpaces)
        {
            retval += string.Join(string.Empty, elements.Skip(i).Take(numOfCharsBetweenSpaces)) + " ";
        }
        return retval.Trim();
    }
    public static string[] SplitIntoTextElements(string input)
    {
        IEnumerable<string> Helper()
        {
            for (var en = StringInfo.GetTextElementEnumerator(input); en.MoveNext();)
                yield return en.GetTextElement();
        }
        return Helper().ToArray();
    }

现在运行我的测试用例

    [Theory]
    [InlineData(null, 1, "")]
    [InlineData(null, 2, "")]
    [InlineData("    ", 3, "")]
    [InlineData("aaaaa", 1, "a a a a a")]
    [InlineData("aaaaa", 2, "aa aa a")]
    [InlineData("aaaaa", 3, "aaa aa")]
    [InlineData("aaaaa", 4, "aaaa a")]
    [InlineData("aaaaa", 6, "aaaaa")]
    [InlineData("aaaaa", 30, "aaaaa")]
    [InlineData("          ", 4, "           ")]
    [InlineData("    a    ", 4, "    a     ")]
    [InlineData("aaa    ", 4, "aaa     ")]
    [InlineData("aaa  ‍  ‍  ‍    ", 4, "aaa  ‍  ‍  ‍     ")]
    public void TestAddSpacesSplitText(string? value, int numOfCharsBetweenSpaces, string expected)
    {
        var actual = value.AddSpacesSplitText(numOfCharsBetweenSpaces);
        Assert.Equal(expected, actual);
    }

它们现在都按预期通过。

我的回答已经很晚了,但你可以使用这个:

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