是否有一种方法可以在.NET(或某种标准扩展方法)中提出枚举问题?
例如,当前项目是枚举中的第一个或最后一个项目:
string s = "";
foreach (var person in PeopleListEnumerator) {
if (PeopleListEnumerator.IsFirstItem) s += "[";
s += person.ToString();
if (!PeopleListEnumerator.IsLastItem) s += ",";
else s += "]";
}
答案 0 :(得分:8)
只是为了好玩,解决一般问题,不需要急切评估并且只有一个局部变量(枚举器除外):
static class TaggedEnumerableExtensions
{
public class TaggedItem<T>
{
public TaggedItem(T value, bool isFirst, bool isLast)
{
IsFirst = isFirst;
IsLast = isLast;
Value = value;
}
public T Value { get; private set; }
public bool IsFirst { get; private set; }
public bool IsLast { get; private set; }
}
public static IEnumerable<TaggedItem<T>> ToTaggedEnumerable<T>(this IEnumerable<T> e)
{
using (var enumerator = e.GetEnumerator()) {
if (!enumerator.MoveNext())
yield break;
var current = enumerator.Current;
if (!enumerator.MoveNext()) {
yield return new TaggedItem<T>(current, true, true);
yield break;
} else {
yield return new TaggedItem<T>(current, true, false);
}
for (;;) {
current = enumerator.Current;
if (!enumerator.MoveNext()) {
yield return new TaggedItem<T>(current, false, true);
yield break;
}
yield return new TaggedItem<T>(current, false, false);
}
}
}
}
测试:
class Program
{
static void Main(string[] args)
{
foreach (var item in Enumerable.Range(0, 10).ToTaggedEnumerable()) {
Console.WriteLine("{0} {1} {2}", item.IsFirst, item.IsLast, item.Value);
}
}
}
答案 1 :(得分:3)
如果您的收藏是一个列表,您可以这样做:
string s = "[" + String.Join(",", PeopleList.ToArray()) + "]";
答案 2 :(得分:2)
不是我知道的。不过,您可以尝试自己编写这样的扩展方法。或者跟踪其他地方的第一个/最后一个项目。
Eric Lippert最近有一个关于这类问题的blog post,以及有关如何修改问题描述以更准确地反映实际需求的一些想法。
在这种情况下,你可能最好使用String.Join和一些LINQ:
String.Join(
",",
(from p in PeopleListEnumerator
select p.ToString()).ToArray()
)
答案 3 :(得分:1)
IEnumerable接口未定义或期望它返回的项目按任何给定顺序。所以“第一”的概念并不总是适用。
然而,对于这种特殊模式,这就是我所做的
StringBuilder result = new StringBuilder();
result.Append( '[' );
foreach( var person in PeopleListEnumerator )
{
if( result.Length > 1 )
result.Append( ',' );
result.Append( person.ToString() );
}
result.Append( ']' );
答案 4 :(得分:1)
使用LINQ,您可以:
string s =
string.Format("[{0}]", string.Join(",",PeopleListEnumerator.Select(p => p.ToString()).ToArray()));
答案 5 :(得分:1)
Jon Skeet写了Smart Enumerations来提供这种功能,它们是MiscUtils库的一部分。
那说你的具体例子最好通过String.Join()方法解决,正如许多其他人所指出的那样。编写一般的string Join(this IEnumerable<T>,string)
扩展并不难,然后可以在任何更多情况下使用,而不必诉诸恼人的临时数组。
答案 6 :(得分:0)
我发现自己定义并使用“bool first”局部变量,例如:
string s = "[";
bool first = true;
foreach (var person in PeopleListEnumerator) {
if (first)
first = false;
else
s += ",";
s += person.ToString();
}
s += "]";
答案 7 :(得分:0)
此代码与您真正想要完成的内容非常匹配:
StringBuilder s = new StringBuilder("[");
string delimiter = "";
foreach (var person in PeopleListEnumerator) {
s.Append(delimiter).Append(person.ToString());
delimiter = ",";
}
return s.Append("]").ToString();
答案 8 :(得分:0)
我给这只猫上皮的方式(是的,有很多方法)将是:
StringBuilder sb = new StringBuilder();
foreach (var person in PeopleListEnumerator )
{
sb.AppendFormat(",{0}", person.ToString());
}
string s = "[" + sb.ToString().Substring(1) + "]";
希望这会有所帮助......
答案 9 :(得分:-2)
在.NET枚举中没有顺序概念,除了值。如果你想要第一个和最后一个枚举,我建议明确定义这些第一个和最后一个值是什么。以下枚举就是一个例子:
public enum PlayerType : byte
{
Starter = byte.MinValue,
RegularPlayer = 1,
BenchWarmer = 2,
Closer = byte.MaxValue
}
然后,您可以表达类似于以下内容的内容:
List<byte> values = new List<byte>((byte[])Enum.GetValues(typeof(PlayerType)));
PlayerType starter = (PlayerType)values.Min();
PlayerType closer = (PlayerType)values.Max();