【问题标题】:Advise to optimize the following code in a better way建议以更好的方式优化以下代码
【发布时间】:2021-10-19 14:21:27
【问题描述】:

我有一些数据存储在字典中,其中的值基本上是一个对象列表,其中几乎没有属性。现在我正在循环如下以获取存储在特定属性中的数据。然后将这些数据添加到下拉列表中(unity UI 下拉列表)

foreach (KeyValuePair<string, List<NameIDValuePair>> kvp in TeamValuePair)
            {
                List<NameIDValuePair> list = kvp.Value;

                if(kvp.Key == teamNames.options[teamNames.value].text)
                {
                    foreach (var rec in list)
                    {
                        screenNamesDropDown.options.Add(new TMP_Dropdown.OptionData { text = rec.ScreenName });
                    }
                }
            }

teamNames 和 screenNamesDropDown 是我的统一 UI 的下拉元素。

NameIdValuePair 的结构如下:

public class NameIdValuePair 
        {
            public string ScreenName { get; private set; }

            public string ScreenId { get; private set; }
        }

我想使用 linq 以更好的方式优化这段代码 - 使其更具可读性。由于我对 linq 还很陌生,因此我不确定在搜索建议时是否使用了正确的关键字,但到目前为止,我在找到任何有用的建议方面并没有取得太大的成功。

谢谢

【问题讨论】:

  • 回答这个问题的最佳方法是,将其发布到Code review
  • LINQ 是一个很好的工具来过滤或选择集合,而不是消耗结果查询。您的代码仅显示您如何使用已有的结果。所以没有什么可以用 LINQ 优化的。换句话说,LINQ 可以帮助构建该字典,但它不能替代 foreach 循环。
  • 为什么要迭代字典TeamValuePair?键不能重复,因此if 中的代码实际上只执行一次(如果键存在)......您可以直接使用给定键的字典索引器获取列表(假设键存在)
  • 不要循环字典,而是尝试TeamValuePair.TryGetValue(teamNames.options[teamNames.value].text, out var list) 来获取您需要的单个列表,或者如果没有该键的条目,那么它将返回 false,您可以跳过它
  • LINQ 非常适合编写紧凑、富有表现力的查询。但它依赖于有一些开销的抽象。因此,如果性能是一个问题,它很少是最好的选择。而且一般来说,可读性通常很难与优化相结合,如果没有非常详细的 cmets,高度优化的代码几乎是无法理解的。

标签: c# linq unity3d


【解决方案1】:

如前所述,不要循环 Dictionary - 我们已经知道键是唯一的 - 您可以简单地使用 Dictionary.TryGetValue

// do this only once! 
var key = teamNames.options[teamNames.value].text;

if (TeamValuePair.TryGetValue(key, out var list))
{
    foreach(var item in list)
    {
        screenNamesDropDown.options.Add(new TMP_Dropdown.OptionData(item.ScreenName));
    }
}

如果你真的想的话,实际上你可以使用 Linq 的唯一地方可能是

var key = teamNames.options[teamNames.value].text;

if (TeamValuePair.TryGetValue(key, out var list))
{
    screenNamesDropDown.options.AddRange(list.Select(item => new TMP_Dropdown.OptionData(item.ScreenName)));
}

如果这样可以更好地阅读是值得怀疑的。

一般来说,问题还在于您是否总是想将Add (AddRange) 转换为screenNamesDropDown.options,或者您是否想要实际替换选项。然后你可以代替AddRange

screenNamesDropDown.options = list.Select(item => new TMP_Dropdown.OptionData(item.ScreenName)).ToList();

【讨论】:

  • 感谢您的评论。我想包含 linq 只是为了看看是否有更好的方法来过滤/选择值并使用 ToList() 将它们放入列表中,并使用 Unity UI Dropdown 提供的 AddOptions 属性将它们直接添加到我的下拉列表中,它可以使用一个字符串列表。在我的情况下,我有两个下拉列表,其中第一个包含所有键的名称。根据在第一个下拉列表中选择的键,应从字典中提取和填充屏幕名称,并使用 AddOptions 函数而不是使用 options.Add 将其包含到下拉列表中
  • 我会测试你的代码,并会在某个时候回复你。再次感谢:)
  • 谢谢。以更好的方式重组我的代码对我很有帮助:)
猜你喜欢
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
  • 2016-03-05
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多