Enfoque StringBuilder
aquí está un Aggregate
con un StringBuilder
. Hay algunas determinaciones de posición que se realizan para limpiar la cadena e insertar el "y", pero todo se hace en el nivel StringBuilder
.
var people = new[]
{
new { Id = 1, Name = "John" },
new { Id = 2, Name = "Mark" },
new { Id = 3, Name = "George" }
};
var sb = people.Aggregate(new StringBuilder(),
(s, p) => s.AppendFormat("{0}:{1}, ", p.Id, p.Name));
sb.Remove(sb.Length - 2, 2); // remove the trailing comma and space
var last = people.Last();
// index to last comma (-2 accounts for ":" and space prior to last name)
int indexComma = sb.Length - last.Id.ToString().Length - last.Name.Length - 2;
sb.Remove(indexComma - 1, 1); // remove last comma between last 2 names
sb.Insert(indexComma, "and ");
// 1:John, 2:Mark and 3:George
Console.WriteLine(sb.ToString());
Un enfoque String.Join
podrían haberse utilizado en su lugar, pero el "y" la eliminación de inserción y coma generaría ~ 2 nuevas cadenas.
Enfoque Regex
Aquí hay otro método que utiliza expresiones regulares que es bastante comprensible (nada demasiado críptica).
var people = new[]
{
new { Id = 1, Name = "John" },
new { Id = 2, Name = "Mark" },
new { Id = 3, Name = "George" }
};
var joined = String.Join(", ", people.Select(p => p.Id + ":" + p.Name).ToArray());
Regex rx = new Regex(", ", RegexOptions.RightToLeft);
string result = rx.Replace(joined, " and ", 1); // make 1 replacement only
Console.WriteLine(result);
El patrón es simplemente ", "
. La magia se encuentra en el RegexOptions.RightToLeft
que hace que la coincidencia se produzca desde la derecha y, por lo tanto, hace que el reemplazo ocurra en la última aparición de coma. No hay un método estático Regex
que acepte el número de reemplazos con el RegexOptions
, de ahí el uso de la instancia.
Pregunta similar: http://stackoverflow.com/questions/788535 – Foole