Hallo an Alle.
Ich versuche gerade einige Sachen mit LINQ zu lösen (auch zur Übung).
Jetzt möchte ich, mit Komma getrennte Elemente, in einem String sortieren.
Ich finde aber nicht heraus, wo ich das .Trim() für die Elemente rein bekomme, oder sollte man vorher ein .Replace(" ", string.Empty) über den ganzen String machen?
.Trim() bei select ist ja zu spät, da ich die Elemente vor dem Sortieren trimmen will.
Wo, bzw. wie kann ich jedes Element vor dem Sortieren trimmen?
using System;
using System.Linq;
namespace SimpleTests
{
class Program
{
static void Main(string[] args)
{
string originString = "en, de, fr, xx , df";
string resultString = string.Join(",", from languageShort in originString.Split(',')
orderby languageShort
select languageShort);
Console.WriteLine("|" + resultString + "|");
Console.ReadLine();
}
}
}
Als Ergebnis soll eigentlich |de,df,en,fr,xx| heraus kommen ...
So geht es zwar, aber eventuell kann man auf das temp verzichten ...
using System;
using System.Linq;
namespace SimpleTests
{
class Program
{
static void Main(string[] args)
{
string originString = "en, de, fr, xx , df";
string resultString = string.Join(",", from languageShort in originString.Split(',')
let temp = languageShort.Trim()
orderby temp
select temp);
Console.WriteLine("|" + resultString + "|");
Console.ReadLine();
}
}
}
Das wäre mit .Replace ... aber ändert den original String... 😦
using System;
using System.Linq;
namespace SimpleTests
{
class Program
{
static void Main(string[] args)
{
string originString = "en, de, fr, xx , df";
originString = originString.Replace(" ", string.Empty);
string resultString = string.Join(",", from languageShort in originString.Split(',')
orderby languageShort
select languageShort);
Console.WriteLine("|" + resultString + "|");
Console.ReadLine();
}
}
}
oder so ...
using System;
using System.Linq;
namespace SimpleTests
{
class Program
{
static void Main(string[] args)
{
string originString = "en, de, fr, xx , df";
string resultString = string.Join(",", from languageShort in originString.Replace(" ", string.Empty).Split(',')
orderby languageShort
select languageShort);
Console.WriteLine("|" + resultString + "|");
Console.ReadLine();
}
}
}
... gibt es ggf. bessere Wege für diese Aufgabe?
**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France
Wenn Du die Query Syntax nutzen willst, gibt es keinen besseren Weg, als mit let ein Zwischenergebnis zu halten.
Wenn Du die Methoden nutzt, dann z.B. so:
string originString = "en, de, fr, xx , df";
string resultParts = originString.Split(',')
.Select(languageShort => languageShort.Trim())
.OrderBy(languageShort => languageShort)
string resultString = string.Join(",", resultParts);
Hallo Hajoseb,
der richtige Platz für ein Trim wäre nachdm du es in die Teile zerlegt hast, die man dann trimmen kann. Also nach einem Split.
var resultString = originString.Split(',').Select(x => x.Trim()).OrderBy(x => x).Aggregate((c, n) => c + ", " + n);
Fast Palladin007's Lösung 😃
Gruss
Coffeebean
Microsoft MVP // Me // Blog // GitHub // @Egghead // All my talks // Speakerdeck
string originString = "en, de, fr, xx , df"; var resultString = originString.Split(',').Select(x => x.Trim()).OrderBy(x => x).Aggregate((c, n) => c + ", " + n); Console.WriteLine("|" + resultString + "|"); Console.ReadLine();
Ich steh eben auf (auch optisch) schönen Code 😉Hat denn das .Aggregate irgendeinen Vorteil gegenüber string.Join(...)
Danke für Eure Anregungen... 👍 Vermutlich gibt es keine "schöneren" Lösungen 😁
Versuch:
using System;
using System.Linq;
namespace SimpleTests
{
class Program
{
static void Main(string[] args)
{ zur Optik
string originString = "en, de, fr, xx , df";
var resultString = originString.Split(',')
.Select(x => x.Trim())
.OrderBy(x => x)
.Aggregate((c, n) => c + "," + n);
Console.WriteLine("|" + resultString + "|");
Console.ReadLine();
}
}
}
Da musste noch das Leerzeichen nach dem "," weg ... 😉
Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 2.3 keine Full Quotes
**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France
Aggregate ist allgemeingültig für IEnumerable.
Ich denke, string.Join ist schneller als die Variante mit Aggregate.
Der Grund ist, dass intern der StringBuilder verwendet wird, der baut genau einen String.
Bei Aggregate würde mit jedem Durchlauf ein String erstellt und im RAM abgelegt.
Eine noch schnellere Variante wäre, vorher die Länge des neuen Strings zu berechnen und dem StringBuilder als Parameter zu übergeben.
Dafür gibt es allerdings keine Methode im .NET, zumindest keine die ich kenne.
Beides fällt aber nur auf, wenn es sich um größere Auflistungen handelt. Bei den 5 Elementen ist das ziemlich egal.
Na, ja.
Hängt also von der Anzahl der nötigen Aufrufe ab.
thx
Hajoseb
P.S. Eh der ewige (innere) Konflikt, ob die Abfrage-Form oder die Lambda-Form ... :evil:
**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France
Das meine ich nicht, der Nachteil fällt bei so wenig Elementen bloß nicht auf.
Wenn Du einen String erzeugst, was Du bei jedem Durchlauf in Aggregate machst, wird zuerst geschaut, ob es bereits einen vorhandenen String im RAM gibt und verwenden Diesen. Gibt es den nicht, wird er neu im RAM abgelegt.
Wenn Du das nun einige 1.000, 100.000 oder mehr hast, dann wird das auf einmal sehr interessant.
Bei 5 Elementen ist das vielleicht nicht einmal messbar.
String.Join macht das etwas anders.
Es hält im Innern einen StringBuilder. Jeder anzuhängende String wird im StringBuilder angehängt.
Der hält die Daten anders und kann am Ende einen einzelnen String erzeugen.
var numbers = Enumerable.Range(0, 50000).Select(x => x.ToString());
var watch = new Stopwatch();
watch.Start();
var aggregateString = numbers.Aggregate((x, y) => x + "." + y);
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
var joinString = string.Join(".", numbers);
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
Console.ReadKey();
Bei mir:
3901
9
Das ist ein stolzer Unterschied 😄
Wenn ich 5 Zahlen nehme, dann dauert die erste Variante eine Millisekunde, die Zweite unter 0.
Hab noch eine Steigerung gefunden 😁
using System;
using System.Linq;
namespace SimpleTests
{
class Program
{
static void Main(string[] args)
{
string originString = "en, de, fr, xx , df";
var resultString = originString.Split(',')
.Select(x => x.Trim())
.OrderBy(x => x)
.Aggregate((c, n) => $"{c},{n}");
Console.WriteLine($"|{resultString}|");
Console.ReadLine();
}
}
}
C# 6 -> $"{...}"
**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France
Das ist ein stolzer Unterschied 😁
Wenn ich 5 Zahlen nehme, dann dauert die erste Variante eine Millisekunde, die Zweite unter 0.
Wow !!! Du hast eine Zeitmaschine Programmiert 8o
unter 0, also kleine 0, also negative Zeit 8)
😁 Hajoseb
**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France
Oha ....
var numbers = Enumerable.Range(0, 50000).Select(x => x.ToString());
var watch = new Stopwatch();
watch.Start();
var aggregateString = numbers.Aggregate((x, y) => x + "." + y);
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
var joinString = string.Join(".", numbers);
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
var newaggregateString = numbers.Aggregate((x, y) => $"{x}.{y}");
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
4403
11
20059 !!!! X( 🤔
Ups ... das $"{....}" sollte man eventuell weniger Einsetzen ⚠
**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France
Jaja, 0 Millisekunden bzw. nicht messbar 😄
Aus der String Interpolation wird ein String.Format gemacht. (So heißt das mit dem $"{....}")
Das ist dafür überhaupt nicht geeignet und auch nicht gedacht.
Außerdem umgeht es das Problem von Aggregate in diesem Anwendungsfall nicht.
Ich ziehe auch meine Theorie zum FastJoin zurück.
Sie ist zwar schnell, aber immer so rund 3 Millisekunden langsamer als string.Join
Zeigen darf ich den Code hier aber nicht, der gehört mir nicht 😄
Verwende einfach string.Join
Das ist genau dafür gemacht und auch im Detail optimiert.