Bei jeder N Zeichen ein Trennzeichen zur Zeichenfolge hinzufügen?


76

Ich habe eine Zeichenfolge, die Binärziffern enthält. Wie trenne ich eine Zeichenfolge nach jeder 8-stelligen?

Angenommen, die Zeichenfolge lautet:

string x = "111111110000000011111111000000001111111100000000";

Ich möchte nach jeweils 8 Zeichen ein Trennzeichen wie (Komma) einfügen.

Ausgabe sollte sein:

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

Dann möchte ich es an eine Liste <> letzte 8 Zeichen zuerst senden, dann die vorherigen 8 Zeichen (außer) und so weiter.

Wie kann ich das machen?


1
Sie können ein char- oder byte-Array verwenden.
AliRıza Adıyahşi


Kann ich das erste mit string.Format () machen? Wenn als wie?
Abdur Rahim

Antworten:


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

Wenn Sie ein Array mit Zeichenfolgen mit acht Zeichen möchten, ist Folgendes wahrscheinlich einfacher:

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

Dadurch wird die Zeichenfolge nur an Stellen aufgeteilt, an denen ein Vielfaches von acht Zeichen davor steht.


1
Es könnte sich lohnen zu behaupten, dass es sich nur um binäre "Ziffern" handelt, nicht um Zeichen: "[01]{8}"
GalacticCowboy

3
Nun, ich hoffe sie wissen, welche Art von Daten sie in diese werfen :)
Joey

Können Sie mir den Teil "$ 0" erklären? Ich bin mir nicht ganz sicher, wie dieser Ausdruck gelesen / ausgewertet werden soll.
Scottmgerstl

1
Im Ersatzteil $0bezieht sich auf das gesamte Spiel ( $1ist die erste Erfassungsgruppe usw.). Sie können auch verwenden $&.
Joey

17
Während die Anfrage war für das Hinter Komma fragen, ob der Entwickler nicht das folgende Komma wollte, konnten sie die regulären Ausdruck ändern . „{8} (?! $)“ , Das eine negative Vorschau verwendet , um sicherzustellen , dass es nicht die überein acht Zeichen am Ende der Zeichenfolge.
Josh Lyon

43

Versuche dies:

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

Ja in der Tat ... Danke @dasbinkeblight
Abdur Rahim

1
Sie brauchen das ToList()übrigens nicht, da string.Joines eine Überlastung gibt, die eineIEnumerable (seit .NET 4) benötigt.
Joey

1
@ Joey Ich weiß, aber ich habe die Frage zunächst falsch verstanden. Ich habe den Teil gelesen, in dem das OP sagt "Dann möchte ich ihn an eine Liste senden <>", und eine Antwort mit ToList()und ohne string.JoinZeile gepostet . Dann habe ich die Frage erneut gelesen, hinzugefügt res = ...und gespeichert, aber vergessen, sie zu entfernen ToList().
Sergey Kalinichenko

1
Hatte ein Problem, nachdem ich eine Erweiterungsmethode erstellt hatte. Wenn die Zeichenfolge kürzer war als das Intervall. if (s.Length <Intervall) gibt s zurück; Aber sonst hat super geklappt.
Joghurt der Weise

Diese Methode schneidet die Länge der Zeichenfolge ab. Wenn die sZeichenfolge 7 weitere Zeichen enthalten würde, würden diese nicht zurückgegeben.
Mort

3

... oder alte Schule:

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
Ich nenne es einfach zu lesen - aber für jeden das Richtige: D Anders als die Regex-Methoden hier ist es das, was die Linq-Methoden hinter den Kulissen tun - durchlaufen und hacken - einfach viel einfacher zu lesen. Ich mag die Batch-Methode oben, das ist eine neue für mich :)
Wolf5370

Dies wird jedoch nicht einmal kompiliert, da lengthes kein Mitglied von ist System.String.
Joey

3

Hässlicher aber weniger Müll:

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

Stringüberladung:

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

Es gibt noch einen anderen Regex-Ansatz:

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

Ich mag diesen Ansatz, da die "Teile verständlich sind", auch wenn es in .NET 3.5

Vielen Dank für die Ergänzungen :) - Ich vergesse immer wieder, die Framework-Kompatibilität zu überprüfen.
Alex

1
Dieser Code entfernt Zeichen. Trennzeichen werden durch Zeichenfolgen ersetzt und Zeichenfolgen gehen verloren.
Mohsen Tavoosi

2

Wenn ich Ihre letzte Anforderung richtig verstehe (mir ist nicht klar, ob Sie die durch Kommas getrennte Zwischenzeichenfolge benötigen oder nicht), können Sie Folgendes tun:

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

Durch die Verwendung von Morelinq .


Wenn nur BatchStandard war :( Auf jeden Fall ist es Hand, über Morelinq zu wissen.

1

Eine Möglichkeit mit 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()
    );

Dieser Code fügt Trennzeichen von rechts nach links ein. Anstelle von links nach rechts
Mohsen Tavoosi

1

Hier auch meine zwei kleinen Cent. Eine Implementierung mit 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();
        }

Sie können es so nennen:

string data = "111111110000000011111111000000001111111100000000";
string output = AddChunkSeparator(data, 8, ',');

Diese Methode schlägt fehl, wenn str null ist oder wenn es kürzer als chunk_len ist
Greg

0

Dies ist viel schneller, ohne das Array zu kopieren (diese Version fügt alle 3 Stellen Leerzeichen ein, aber Sie können es an Ihre Bedürfnisse anpassen).

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

Ich verstehe das nicht valueField a double? Sie konvertieren die Eingabezeichenfolge in double, um sie in der Funktion zu verwenden und sie dann in string und charArray umzuwandeln. Würde es Ihnen etwas ausmachen, den Code ein wenig zu kommentieren?
Joze

Ich hatte keine Eingabezeichenfolge. Ich hatte gerade einen doppelten Wert, deshalb valueFiledist doppelt. Wenn Sie einen Zeichenfolgenwert haben, können Sie eine Zeichenfolge valueFilederstellen und die erste Zeile in ändern char[] ins = valueField.ToCharArray();.
Mateusz Puwałowski

0

Ein wenig zu spät zur Party, aber hier ist ein vereinfachter LINQ-Ausdruck, um eine Eingabezeichenfolge xin Gruppen zu unterteilen, ndie durch eine andere Zeichenfolge getrennt sind sep:

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

Ein kurzer Überblick darüber, was hier passiert:

  • xwird als behandelt IEnumberable<char>, wo die InSetsOfErweiterungsmethode ins Spiel kommt.
  • InSetsOf(n)gruppiert Zeichen zu einem IEnumerablevon IEnumerable- Jeder Eintrag in der äußeren Gruppierung enthält eine innere Gruppe von nZeichen.
  • Innerhalb der SelectMethode wird jede Gruppe von nZeichen mithilfe des String()Konstruktors, der ein Array von enthält, wieder in eine Zeichenfolge umgewandelt chars.
  • Das Ergebnis von Selectist jetzt ein IEnumerable<string>, an das übergeben wird, String.Joinum die sepZeichenfolge wie jedes andere Beispiel zu verschachteln .

0

Ich habe es mit Pattern & Matcher folgendermaßen gemacht:

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

Wo:

inputgibt die Eingabezeichenfolge an. Überprüfen Sie den Abschnitt mit den Ergebnissen.

insertionzeigt Zeichenfolge zwischen diesen Zeichen einfügen an. Zum Beispiel Komma (,), Start (*), Hash (#).

interval Gibt an, in welchem ​​Intervall Sie Einfügezeichen hinzufügen möchten.

inputgibt die Eingabezeichenfolge an. Überprüfen Sie den Abschnitt mit den Ergebnissen. Überprüfen Sie den Abschnitt mit den Ergebnissen. Hier habe ich bei jedem 4. Zeichen eine Einfügung hinzugefügt.

Ergebnisse:

E / A: 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

Hoffe das hilft.


-1

Ich bin mehr als spät mit meiner Antwort, aber Sie können diese verwenden:

    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

Für jeden 1 Charakter kannst du diesen Einzeiler machen:

string.Join(".", "1234".ToArray()) //result: 1.2.3.4
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.