Autor Beitrag
haschme
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 57
Erhaltene Danke: 1



BeitragVerfasst: Mi 18.04.18 16:15 
Hallo zusammen,


ich würde meinen vorhandenen Code um einen Teilstring in einen vorhandenen String einzufügen gerne performanter machen und durch ein RegEx.Replace ersetzen.

Dabei gehe ich bisher folgendermaßen vor:
ausblenden C#-Quelltext
1:
Ergebnis = Regex.Replace("Dies ist meine Zeile""^(.{1})""Das ");					

Als Ergebnis würde ich mir folgendes wünschen:
ausblenden Quelltext
1:
"Das ist meine Zeile"					

Leider wird der alte Text aber nicht überschrieben sondern aufgerückt, das Ergebnis ist also folgendes:
ausblenden Quelltext
1:
"Das Dies ist meine Zeile"					

Hat vielleicht jemand eine Idee oder einen Tipp wie ich das beheben könnte?

Vielen Dank im Vorraus!

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Moderiert von user profile iconTh69: Code-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 18.04.18 16:29 
Ersetze die 1 in deinem Regex durch eine 5.


Zuletzt bearbeitet von Ralf Jansen am Mi 18.04.18 16:32, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: haschme
lapadula
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Mi 18.04.18 16:31 
Oder direkt das Wort:

ausblenden C#-Quelltext
1:
Regex.Replace("Dies ist meine Zeile""^(Dies)""Das");					

Für diesen Beitrag haben gedankt: haschme
haschme Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 57
Erhaltene Danke: 1



BeitragVerfasst: Mi 18.04.18 16:49 
Danke für die schnelle Antwort!

Wonach ich suche wäre etwas vergleichbares wie String.Insert.
Allerdings wie schon gesagt wäre es auch wichtig, dass der alte String an der zu ersetzenden Position nicht aufgerückt sondern überschrieben wird.

Kann man sowas auch mit RegEx realisieren? Bzw. gibt es andere performante Alternativen die bei meinem Problem weiterhelfen würden?

Zu Beginn habe ich immer damit gearbeitet:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
        private static StringBuilder writeColumnSB = new StringBuilder();

        public static string WriteColumnToLine(string line, int start, int length, string insertValue)
        {
            writeColumnSB.Clear();
            writeColumnSB.Append(line.Substring(0, start - 1));
            writeColumnSB.Append(insertValue.PadRight(length, ' '));
            writeColumnSB.Append(line.Substring((start + length) - 1));

            return writeColumnSB.ToString();
        }

Gibt es da eine Verbesserungsmöglichkeit?

Viele Grüße!

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 18.04.18 18:01 
Anders

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
public static string WriteColumnToLine(string line, int start, int length, string insertValue)
{
  var writeColumnSB = new StringBuilder(line);
  writeColumnSB.Remove(start, length);
  writeColumnSB.Insert(start, insertValue);
  return writeColumnSB.ToString();
}


Wie und ob das in deiner Umgebung besser performt musst du selber rausfinden.
Hast du den überhaupt ein Performance Problem? Wenn ja hast du denn gemessen das das Problem an dieser Stelle liegt?
Wie hast du start und length ermittelt? Das ist möglicherweise Teil des Problems, wenn es denn ein Problem gibt.

Für diesen Beitrag haben gedankt: haschme
lapadula
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Mi 18.04.18 18:05 
Regex replace rückt doch gar nichts auf. Du hast bei “das “ ein Leerzeichen.

Für diesen Beitrag haben gedankt: haschme
haschme Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 57
Erhaltene Danke: 1



BeitragVerfasst: Do 19.04.18 15:29 
Ich bin jetzt doch erstmal bei der Stringbuilder-Variante geblieben.
Mit RegEx kam ich in dem Fall nicht ganz so weit.
Es handelt sich hierbei um ein Selektionstool mit zusätzlicher Codierungsmöglichkeit.
Da die Performance der Selektionen in Ordnung war konnte ich darauf schließen, dass die Codierung nicht schnell genug war.
Gemessen habe ich das mit einem simplen Timer da ich leider kein Tool wie Red Gate oä. zur Hand habe^^

Das es auch schneller geht weiß ich, da es sich um eine Neuentwicklung handelt und die alte Version in Delphi programmiert wurde.
Die Delphi Version arbeitet bei der Codevergabe mit der Move-Methode.
Die Delphi-Version brauch für 2,6 Mio Datensätze 48 Sekunden wärend meine C# Variante unter den gleichen Einstellungen leider noch 2 Minuten in Anspruch nimmt.

Gibt es etwas vergleichbares wie das Delphi-Move in C#?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 19.04.18 23:05 
So wie strings in einer Garbage Collected Sprache üblicherweise funktionieren schwierig. Die sind nunmal unveränderlich (immutable).
Darum fragt ich auch insbesondere ob du da was gemessen hast. (z.b. durch passenden Einbau der StopWatch Klasse).
Vermutung ist das da die meiste Zeit beim Allokieren neuen Speichers drauf geht da du die Daten aus einem string in einen Stringbuilder und zurück in einen string kopierst bzw. kopieren musst.

Heißt Beschleunigungspotential (in einer Single-Thread Anwendung) läge also darin auf strings zu verzichten und direkt nur an Byte Arrays oder nur via Stringbuilder zu arbeiten.
Das ist vermutlich aber für dich keine Option da vieles drumherum was man gern aus dem Framework verwenden würde string basiert ist und man Alternativen nutzen müsste. Die nicht immer so einfach zu haben sind.
Und die hätten dann erst recht keinerlei Ähnlichkeit mehr zu einer Delphi Lösung.

Für diesen Beitrag haben gedankt: haschme
haschme Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 57
Erhaltene Danke: 1



BeitragVerfasst: Fr 20.04.18 09:36 
Hallo danke nochmal für die Antwort.
Ja das programmieren in Byte-Arrays ist zwar schön schnell kommt aber wie du schon geschrieben hattest für mich erstmal nicht in Frage.

Aber (vielleicht ist das ja nochmal für andere interesannt) ich konnte die Performance tatsächlich nochmal etwas erhöhen indem ich auf den StringBuilder komplett verzichte.

Stattdessen verwende ich die String.Concat() - Methode, die in manchen Fällen wohl schneller sein soll als der StringBuilder.
Außerdem fällt hier die schon erwähnte Umwandlung von String zu Stringbuilder und zurück zu String weg.

Von der Geschwindigkeit her reicht mir die jetzige Lösung ersteinmal.

Vielen Dank für eure Kommentare, der Thread kann somit geschlossen werden.
lapadula
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Fr 20.04.18 09:47 
Habe den StringBuilder mit Regex verglichen und dabei kam folgendes Ergebnis bei raus:

Schleifendurchlauf / Stringbuilder Zeit in µs / Regex Zeit in µs / Prozent
1.000 / 317µs / 1281 µs / 404%
10.000 / 1783µs / 9589 µs / 537%
100.000 / 15343 µs / 81283 / 529%

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
    //StringBuilder("Dies ist meine Zeile", 0, 4, "Das");
    RegexTest("Dies ist meine Zeile");
}
watch.Stop();
int microSeconds = (int)(watch.ElapsedTicks * 1.0e6 / Stopwatch.Frequency + 0.4999);
MessageBox.Show(microSeconds.ToString());

Für diesen Beitrag haben gedankt: haschme