加入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
保持简单。