加入List 和Commas Plus“和”Last Element

我知道我可以想出办法,但我想知道是否有更简洁的解决方案。 总是有String.Join(", ", lList)lList.Aggregate((a, b) => a + ", " + b); 但我想为最后一个添加一个例外,将", and "作为其连接字符串。 Aggregate()在我可以使用的地方有一些索引值吗? 谢谢。

你可以做到这一点

 string finalString = String.Join(", ", myList.ToArray(), 0, myList.Count - 1) + ", and " + myList.LastOrDefault(); 

这是一个解决方案,它使用空列表和列表,其中包含一个项目:

C#

 return list.Count() > 1 ? string.Join(", ", list.Take(list.Count() - 1)) + " and " + list.Last() : list.FirstOrDefault(); 

VB

 Return If(list.Count() > 1, String.Join(", ", list.Take(list.Count() - 1)) + " and " + list.Last(), list.FirstOrDefault()) 

我使用以下扩展方法(也有一些代码保护):

 public static string OxbridgeAnd(this IEnumerable collection) { var output = String.Empty; var list = collection.ToList(); if (list.Count > 1) { var delimited = String.Join(", ", list.Take(list.Count - 1)); output = String.Concat(delimited, ", and ", list.LastOrDefault()); } return output; } 

这是一个unit testing:

  [TestClass] public class GrammarTest { [TestMethod] public void TestThatResultContainsAnAnd() { var test = new List { "Manchester", "Chester", "Bolton" }; var oxbridgeAnd = test.OxbridgeAnd(); Assert.IsTrue( oxbridgeAnd.Contains(", and")); } } 

编辑

此代码现在处理null和单个元素:

  public static string OxbridgeAnd(this IEnumerable collection) { var output = string.Empty; if (collection == null) return null; var list = collection.ToList(); if (!list.Any()) return output; if (list.Count == 1) return list.First(); var delimited = string.Join(", ", list.Take(list.Count - 1)); output = string.Concat(delimited, ", and ", list.LastOrDefault()); return output; } 

此版本枚举一次值,并使用任意数量的值:

 public static string JoinAnd(string separator, string sepLast, IEnumerable values) { var sb = new StringBuilder(); var enumerator = values.GetEnumerator(); if (enumerator.MoveNext()) { sb.Append(enumerator.Current); } object obj = null; if (enumerator.MoveNext()) { obj = enumerator.Current; } while (enumerator.MoveNext()) { sb.Append(separator); sb.Append(obj); obj = enumerator.Current; } if (obj != null) { sb.Append(sepLast); sb.Append(obj); } return sb.ToString(); } 

此版本仅枚举一次值,并适用于任意数量的值。

(@Grastveit的改进答案 )

我将它转换为扩展方法并添加了一些unit testing。 添加了一些空检查。 此外,我修复了一个错误,如果values集合中的项目包含null ,并且它是最后一个,它将被跳过。 这与String.Join()现在在.NET Framework中的行为方式不对应。

 #region Usings using System; using System.Collections.Generic; using System.Text; #endregion namespace MyHelpers { public static class StringJoinExtensions { public static string JoinAnd(this IEnumerable values, string separator, string lastSeparator = null) { if (values == null) throw new ArgumentNullException(nameof(values)); if (separator == null) throw new ArgumentNullException(nameof(separator)); var sb = new StringBuilder(); var enumerator = values.GetEnumerator(); if (enumerator.MoveNext()) sb.Append(enumerator.Current); bool objectIsSet = false; object obj = null; if (enumerator.MoveNext()) { obj = enumerator.Current; objectIsSet = true; } while (enumerator.MoveNext()) { sb.Append(separator); sb.Append(obj); obj = enumerator.Current; objectIsSet = true; } if (objectIsSet) { sb.Append(lastSeparator ?? separator); sb.Append(obj); } return sb.ToString(); } } } 

这是一些unit testing

 #region Usings using MyHelpers; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Linq; #endregion namespace UnitTests { [TestClass] public class StringJoinExtensionsFixture { [DataTestMethod] [DataRow("", "", null, null)] [DataRow("1", "1", null, null)] [DataRow("1 and 2", "1", "2", null)] [DataRow("1, 2 and 3", "1", "2", "3")] [DataRow(", 2 and 3", "", "2", "3")] public void ReturnsCorrectResults(string expectedResult, string string1, string string2, string string3) { var input = new[] { string1, string2, string3 } .Where(r => r != null); string actualResult = input.JoinAnd(", ", " and "); Assert.AreEqual(expectedResult, actualResult); } [TestMethod] public void ThrowsIfArgumentNulls() { string[] values = default; Assert.ThrowsException(() => StringJoinExtensions.JoinAnd(values, ", ", " and ")); Assert.ThrowsException(() => StringJoinExtensions.JoinAnd(new[] { "1", "2" }, null, " and ")); } [TestMethod] public void LastSeparatorCanBeNull() { Assert.AreEqual("1, 2", new[] { "1", "2" } .JoinAnd(", ", null), "lastSeparator is set to null explicitly"); Assert.AreEqual("1, 2", new[] { "1", "2" } .JoinAnd(", "), "lastSeparator argument is not specified"); } [TestMethod] public void SeparatorsCanBeEmpty() { Assert.AreEqual("1,2", StringJoinExtensions.JoinAnd( new[] { "1", "2" }, "", ","), "separator is empty"); Assert.AreEqual("12", StringJoinExtensions.JoinAnd( new[] { "1", "2" }, ",", ""), "last separator is empty"); Assert.AreEqual("12", StringJoinExtensions.JoinAnd( new[] { "1", "2" }, "", ""), "both separators are empty"); } [TestMethod] public void ValuesCanBeNullOrEmpty() { Assert.AreEqual("-2", StringJoinExtensions.JoinAnd( new[] { "", "2" }, "+", "-"), "1st value is empty"); Assert.AreEqual("1-", StringJoinExtensions.JoinAnd( new[] { "1", "" }, "+", "-"), "2nd value is empty"); Assert.AreEqual("1+2-", StringJoinExtensions.JoinAnd( new[] { "1", "2", "" }, "+", "-"), "3rd value is empty"); Assert.AreEqual("-2", StringJoinExtensions.JoinAnd( new[] { null, "2" }, "+", "-"), "1st value is null"); Assert.AreEqual("1-", StringJoinExtensions.JoinAnd( new[] { "1", null }, "+", "-"), "2nd value is null"); Assert.AreEqual("1+2-", StringJoinExtensions.JoinAnd( new[] { "1", "2", null }, "+", "-"), "3rd value is null"); } } } 

我能想到的最简单的方法就是这样…… print(’,’。join(a [0:-1])+’和’+ a [-1])

a = [a,b,c,d]

print(’,’。join(a [0:-1])+’和’+ a [-1])

a,b,c和d

或者,如果您不喜欢加拿大语法,牛津逗号和额外的曲线:

print(’,’。join(a [0:-1])+’和’+ a [-1])

a,b,c和d

保持简单。