.net 枚举第一个和最后一个

发布于 2024-07-25 05:39:22 字数 304 浏览 8 评论 0原文

.NET(或某种标准扩展方法)中有没有办法提出枚举问题?

例如,当前项是枚举中的第一项还是最后一项:

string s = "";

foreach (var person in PeopleListEnumerator) {

  if (PeopleListEnumerator.IsFirstItem) s += "[";

  s += person.ToString();

  if (!PeopleListEnumerator.IsLastItem) s += ",";
  else s += "]";
}

is there a way in .NET (or some sort of standard extension methods) to ask questions of an enumeration?

For example is the current item the first or last item in the enumeration:

string s = "";

foreach (var person in PeopleListEnumerator) {

  if (PeopleListEnumerator.IsFirstItem) s += "[";

  s += person.ToString();

  if (!PeopleListEnumerator.IsLastItem) s += ",";
  else s += "]";
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

翻了热茶 2024-08-01 05:39:23

使用 LINQ,您可以执行以下操作:

string s = 
    string.Format("[{0}]", string.Join(",",PeopleListEnumerator.Select(p => p.ToString()).ToArray()));

Using LINQ, you can do:

string s = 
    string.Format("[{0}]", string.Join(",",PeopleListEnumerator.Select(p => p.ToString()).ToArray()));
岁月静好 2024-08-01 05:39:23

我发现自己定义并使用“bool first”局部变量,例如:

string s = "[";
bool first = true;

foreach (var person in PeopleListEnumerator) {

  if (first)
    first = false;
  else
    s += ",";
  s += person.ToString();
}
s += "]";

I find myself defining and using a "bool first" local variable, for example:

string s = "[";
bool first = true;

foreach (var person in PeopleListEnumerator) {

  if (first)
    first = false;
  else
    s += ",";
  s += person.ToString();
}
s += "]";
音盲 2024-08-01 05:39:23

此代码与您真正想要完成的任务非常匹配:

StringBuilder s = new StringBuilder("[");
string delimiter = "";

foreach (var person in PeopleListEnumerator) {  
  s.Append(delimiter).Append(person.ToString());
  delimiter = ",";
}

return s.Append("]").ToString();

This code closely matches what you really want to accomplish:

StringBuilder s = new StringBuilder("[");
string delimiter = "";

foreach (var person in PeopleListEnumerator) {  
  s.Append(delimiter).Append(person.ToString());
  delimiter = ",";
}

return s.Append("]").ToString();
陌上青苔 2024-08-01 05:39:23

我给这只猫剥皮的方法(是的,有很多方法)是:

StringBuilder sb = new StringBuilder();

foreach (var person in PeopleListEnumerator )
{
    sb.AppendFormat(",{0}", person.ToString());
}

string s = "[" + sb.ToString().Substring(1) + "]";

希望这有帮助......

The way I'd skin this cat (yes, there are that many ways) would be:

StringBuilder sb = new StringBuilder();

foreach (var person in PeopleListEnumerator )
{
    sb.AppendFormat(",{0}", person.ToString());
}

string s = "[" + sb.ToString().Substring(1) + "]";

Hope this helps...

奶茶白久 2024-08-01 05:39:23

在 .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();

In .NET enumerations have no concept of order, except by value. If you want a first and last enumeration I would suggest explicitly defining what these first and last values are. The following enumeration is an example of this:

public enum PlayerType : byte
{
    Starter = byte.MinValue,
    RegularPlayer = 1,
    BenchWarmer = 2,
    Closer = byte.MaxValue
}

You can then express something similar to the following:

List<byte> values = new List<byte>((byte[])Enum.GetValues(typeof(PlayerType)));

PlayerType starter = (PlayerType)values.Min();
PlayerType closer = (PlayerType)values.Max();
无语# 2024-08-01 05:39:22

只是为了好玩,针对一般问题的解决方案不需要急于求值并且具有单个局部变量(枚举器除外):

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);
        }
    }
}

Just for the sake of fun, a solution to the general problem that doesn't require eager evaluation and has a single local variable (except the enumerator):

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);
            }
        }
    }
}

Test:

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);
        }
    }
}
只是偏爱你 2024-08-01 05:39:22

如果您的集合是列表,您可以执行以下操作:

string s = "[" + String.Join(",", PeopleList.ToArray()) + "]";

If your collection is a List, you can do:

string s = "[" + String.Join(",", PeopleList.ToArray()) + "]";
止于盛夏 2024-08-01 05:39:22

从来没听说过。 不过,您可以尝试自己编写此类扩展方法。 或者在其他地方跟踪第一个/最后一个项目。

Eric Lippert 有一篇博客文章最近关于此类问题以及关于如何修改问题描述以更准确地反映您实际想要的内容的一些想法。

您最好使用 String.Join 和一些 LINQ在这种情况下:

String.Join(
  ",",
  (from p in PeopleListEnumerator
  select p.ToString()).ToArray()
)

Not that I know of. You can try writing such extension methods yourself, though. Or keep track of the first/last item elsewhere.

Eric Lippert had a blog post about that kind of problem recently along with some thoughts about how to modify your problem description to more accurately reflect what you actually want.

You're probably better off using a String.Join with some LINQ in this case:

String.Join(
  ",",
  (from p in PeopleListEnumerator
  select p.ToString()).ToArray()
)
路弥 2024-08-01 05:39:22

IEnumerable 接口不定义也不期望它返回的项目按任何给定的顺序排列。 所以“第一”的概念并不总是适用。

然而,对于这个特定的模式,这就是我所做的

StringBuilder result = new StringBuilder();
result.Append( '[' );

foreach( var person in PeopleListEnumerator )
{
    if( result.Length > 1 )
        result.Append( ',' );
    result.Append( person.ToString() );
}

result.Append( ']' );

The IEnumerable interface does not define or expect the items that it returns to be in any given order. So the concept of "First" doesn't always apply.

However, for this particular pattern this is what I do

StringBuilder result = new StringBuilder();
result.Append( '[' );

foreach( var person in PeopleListEnumerator )
{
    if( result.Length > 1 )
        result.Append( ',' );
    result.Append( person.ToString() );
}

result.Append( ']' );
肤浅与狂妄 2024-08-01 05:39:22

Jon Skeet 编写了智能枚举来提供此功能某种功能,它们是 MiscUtils 库的一部分。

这就是说,正如许多其他人指出的那样,您的具体示例最好通过 String.Join() 方法来解决。 编写通用的 string Join(this IEnumerable,string) 扩展并不难,并且可以在任何更多情况下使用,而不必求助于烦人的临时数组。

Jon Skeet wrote Smart Enumerations to provide this sort of functionality and they are part of the MiscUtils library.

That said your specific example is best solved by the String.Join() approach as many others have pointed out. Writing a general string Join(this IEnumerable<T>,string) extension is not hard and is then usable in any more situations without having to resort to annoying temporary arrays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文