Подход StringBuilder
Вот Aggregate
с StringBuilder
.Есть некоторые определения положения, которые сделаны, чтобы очистить строку и вставить «и», но все это делается на уровне 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());
Подход String.Join
можно было бы использовать вместо этого, ноВставка "и" и удаление запятой приведут к генерации ~ 2 новых строк.
Подход Regex
Вот еще один подход с использованием регулярных выражений, который вполне понятен (ничего слишком загадочного).
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);
Шаблон просто ", "
.Магия заключается в RegexOptions.RightToLeft
, который заставляет совпадение происходить справа и тем самым заставляет замену происходить при последнем появлении запятой.Не существует статического метода Regex
, который принимает число замен на RegexOptions
, следовательно, используется экземпляр.