Try This
var source = GetTheString();
var reversed = source.Reverse().Select(x => x.ToString()).Aggregate((x,y) => x + "." + y);
EDYCJA
To rozwiązanie jest zdecydowanie zmierzające do "sprytnego" końca. Prawdopodobnie o wiele bardziej wydajne będzie użycie StringBuilder do zbudowania łańcucha. To rozwiązanie tworzy wiele pośrednich ciągów.
EDIT2
Było trochę debata o względnej prędkości „sprytnego” rozwiązania vs. podejścia StringBuilder. Napisałem szybki test porównawczy, aby zmierzyć podejście. Zgodnie z oczekiwaniami StringBuilder jest szybszy.
- normalny agregatów (100 elementy): 00: 00: 00,0418640
- WithStringBuilder (100 elementów): 00: 00: 00,0040099
- normalny kruszywa (1000 elementów): 00: 00: 00,3062040
- WithStringBuilder elementy (1000): 00: 00: 00,0405955
- kruszywa normalny (10000) elementy: 00: 00: 03,0270392
- WithStringBuilder (10000 elementy) 00: 00: 00,4149977
Jednak to, czy różnica prędkości jest istotna, zależy w znacznym stopniu od miejsca, w którym jest faktycznie używana w aplikacji.
Kod testu porównawczego.
public static class AggregateUnchanged {
public static string Run(string input) {
return input
.Reverse()
.Select(x => x.ToString())
.Aggregate((x, y) => x + "." + y);
}
}
public static class WithStringBuilder {
public static string Run(string input) {
var builder = new StringBuilder();
foreach (var cur in input.Reverse()) {
builder.Append(cur);
builder.Append('.');
}
if (builder.Length > 0) {
builder.Length = builder.Length - 1;
}
return builder.ToString();
}
}
class Program {
public static void RunAndPrint(string name, List<string> inputs, Func<string, string> worker) {
// Test case. JIT the code and verify it actually works
var test = worker("123456");
if (test != "6.5.4.3.2.1") {
throw new InvalidOperationException("Bad algorithm");
}
var watch = new Stopwatch();
watch.Start();
foreach (var cur in inputs) {
var result = worker(cur);
}
watch.Stop();
Console.WriteLine("{0} ({2} elements): {1}", name, watch.Elapsed, inputs.Count);
}
public static string NextInput(Random r) {
var len = r.Next(1, 1000);
var builder = new StringBuilder();
for (int i = 0; i < len; i++) {
builder.Append(r.Next(0, 9));
}
return builder.ToString();
}
public static void RunAll(List<string> input) {
RunAndPrint("Normal Aggregate", input, AggregateUnchanged.Run);
RunAndPrint("WithStringBuilder", input, WithStringBuilder.Run);
}
static void Main(string[] args) {
var random = new Random((int)DateTime.Now.Ticks);
RunAll(Enumerable.Range(0, 100).Select(_ => NextInput(random)).ToList());
RunAll(Enumerable.Range(0, 1000).Select(_ => NextInput(random)).ToList());
RunAll(Enumerable.Range(0, 10000).Select(_ => NextInput(random)).ToList());
}
}
Naprawdę chcesz kropkę po ostatnim 1? Jeśli tak, to nieznacznie zmienia problem. –
Tak, to nie było jasne. To naprawdę nie ma znaczenia, wezmę rozwiązania, które robią to w obie strony. –