【问题标题】:Nested Loop select the minimum defined value asp.net嵌套循环选择最小定义值 asp.net
【发布时间】:2021-05-10 00:55:18
【问题描述】:

我有一个状态列表,这些状态定义为按从最小值到最大值排序。顺序如下:

取消 - 完成 - 草稿 - 预订 - 保留 - 订购 - 确认

所以取消是最小状态,确认是最大状态。我可能有不同状态的不同实例,所以我使用 for-each 循环遍历所有状态,并选择循环中存在的最小状态。

也就是说:如果在列表中我有状态 [完整、保留、草稿、已订购],我需要检查所有值并选择完整 - 因为它似乎是最小状态。或者 如果我有 [reserved,confirmed,ordered,draft,cancelled,confirmed,confirmed] 我需要选择取消的值,因为它似乎是最小值。

我正在做以下检查,但它似乎不起作用:

        string globstatus = " ";
        foreach (var currentstatus in list)
        {
            if (currentstatus == "cancelled")
            {
                globstatus = "cancelled";
            }
            else
            {
                if (globstatus == "cancelled")
                {
                    return globstatus;
                }
                else
                {
                    if (currentstatus == "complete")
                    {
                        globstatus = "complete";
                    }
                    else
                    {
                        if (globstatus == "complete")
                        {
                            return globstatus;
                        }
                        else
                        {
                            if (currentstatus == "draft")
                            {
                                globstatus = "draft";
                            }
                            else
                            {
                                if (globstatus == "reservation")
                                {
                                    return globstatus;
                                }
                                else
                                {
                                    if (currentstatus == "reserved")
                                    {
                                        globstatus = "reserved";
                                    }
                                    else
                                    {
                                        if (globstatus == "ordered")
                                        {
                                            return globstatus;
                                        }
                                        else
                                        {
                                            if (currentstatus == "confirmed")
                                            {
                                                globstatus = "confirmed";
                                            }
                                            else
                                            {
                                                return currentstatus;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                    }
                }
            }
        }

        return globstatus;

实现所需行为的最佳解决方案是什么?

【问题讨论】:

  • currststatus?你的意思是currentstatus 对吗?
  • @SirStopIt 是的,抱歉我打错了。谢谢指正。

标签: asp.net-core nested-loops


【解决方案1】:

我发现一个经验法则很有帮助,如果我需要超过三个级别的大括号​​,我需要重新考虑我的代码。很难理解,容易出错,调试起来简直就是一场噩梦。我建议这适用于这里 - 尝试遵循所有嵌套 if..else 语句的流程非常困难。

使用枚举

我首选的解决方案是使用枚举来实现这一点,例如:

var list = new List<Status>
{
    Status.Complete,
    Status.Draft,
    Status.Draft,
    Status.Confirmed
};

var minStatus = (Status)list.Select(l => (int)l).Min();
// minStatus = Status.Complete

public enum Status
{
    Cancelled,
    Complete,
    Draft,
    Reservation,
    Reserved,
    Ordered,
    Confirmed
}

它是如何工作的: 默认情况下,枚举给每个值一个从零开始的整数,即Cancelled = 0Complete = 1 等等。如果你愿意,你可以用你自己的值覆盖它(例如,如果你想组合多个值,则为 1/2/4/8/16)。

我建议对此类事情使用Enum 类型,而不是字符串。它有助于避免拼写错误,让查看您的代码的其他人清楚地了解您的程序如何工作及其流程,并以简单字符串所不具备的方式表示层次结构。 (例如 - 'complete' 出现在 'draft' 之前还是之后?如果没有上下文,我想大多数人会说 after,但在这种情况下它出现在 before - 那使用枚举时更明显。)

将字符串解析为枚举

但是,如果状态必须是字符串,您可以将它们解析为一个枚举,如下所示:

var stringList = new List<string>
{
    "complete",
    "draft",
    "draft",
    "confirmed",
    "this will be ignored"
};

var statusList = new List<int>();
foreach (var str in stringList)
{
    if(Enum.TryParse(typeof(Status), str, ignoreCase: true, out object? parsed) && parsed is Status status)
    {
        statusList.Add((int)status);
    }
}

var minStatus = (Status)statusList.Min();
// minStatus = Status.Complete

但是,如果可以重构您的代码以首先使用 Enum,那将是一个更好的解决方案,而且速度更快,因为解析字符串会产生可以避免的开销。

【讨论】:

  • 非常感谢。我使用 Parse String to Enum 来解决问题。
  • 在使用枚举时,将项目添加到列表中。 foreach(Model.Sessions 中的 var st){ list.Add(st.State); } -- 我收到一个错误 - 无法将字符串转换为状态。
  • 听起来 st.State 是一个字符串值,并且列表需要一个 Enum Status 值。您是否首先将字符串正确解析为枚举?
猜你喜欢
  • 2021-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 1970-01-01
  • 2012-04-26
相关资源
最近更新 更多