【问题标题】:Growing and shrinking a List<int> vs a big sized bool Array using the index as value使用索引作为值来扩大和缩小 List<int> 与大型布尔数组
【发布时间】:2018-12-20 02:02:28
【问题描述】:

我无法确定对于我的应用程序来说,使用一个增长和缩小的 List 与使用一个大的 bool Array 是否更有效。

为了扩展这种比较和实际情况,以下是我认为我拥有的每个选项的示例:

选项 1(列表):

public List<int> list = new List<int>();
while (true) { // game loop
    list.Add(Random.Range(0-300));
    list.Add(Random.Range(0-300));
    ...  // maximum of 10 of these can happen

    if (list.Contains(42)) { // roughly 10 - 50 of these checks can be true
        list.Remove(42);
    }
}

选项 2(数组):

bool[] arr = new bool[300];
while (true) { // game loop
    arr[Random.Range(0-300)] = true;
    arr[Random.Range(0-300)] = true;
    ... // maximum of 10 of these can happen

    for (int i = 0; i < 300; i++) {
        if (arr[i]) { // roughly 10 - 50 of these checks can be true
            arr[i] = false;
        }
    }
}

所以基本上我的问题是:

在什么时候过多的.Contains 检查变得比for 循环在每个可能的元素上更昂贵(基于我的范围)?

重要

这不是一个列表与数组的问题。由于条件检查,数据类型很重要。所以这是一个整数列表与布尔数组的比较,因为这两个选项可以给我相同的结果。

【问题讨论】:

  • 您的两个版本的代码似乎没有做同样的事情。在某处打错字?
  • 猜猜你应该搜索的是 contains 是如何实现的?根据 MSDN 文档,它进行线性搜索,所以 O(N),这有点类似于我猜的搜索数组。不错的链接@mjwills。
  • 我不能只对它进行基准测试的原因是因为它不像将两者放在一起那么容易。我必须实际构建应用程序,在那个阶段我会过度投资于一个选项。在省略号 ... 之后发生了更多事情。
  • Contains(42) 与数组的等价物将只是if(arr[42]),而要“删除”它只是arr[42] = false;,这显然更快。基本上,您用查找时间换取空间,这通常是与性能的权衡。要记住的另一个区别是列表可以包含重复项,但数组实现仅指示一个数字是否是随机选择的,而不是多少次。

标签: c# arrays list game-development


【解决方案1】:

我会说数组实现会快得多。除了调用List.Add(T) 或List.Remove(T) 时在内部调整数组大小的成本之外,如果您检查List implementation code。你会注意到List.Contains(T) 和List.Remove(T) 都在使用IndexOf(T),我相信这是在内部循环/迭代列表。在您的示例中,您想调用 List.Contains(T) 和 List.Remove(T) 大约 10-50 次。这意味着在最好的情况下它会花费你 20(包含+删除),但在最坏的情况下它会花费你 (N * 50) + N 其中 N 是列表中的项目数。

有了这些信息,我可以得出结论,如果你的列表越来越大,性能会更差。

如果您更关注性能,也许值得看看HashSet 数据结构。它在look up 和remove 操作中的better performance 比List 多。

【讨论】:

    【解决方案2】:

    这是 Jon Skeet 对 for、foreach、EnumerableForEach 和 Sum 的 Array vs List 的有趣文章:

    https://codeblog.jonskeet.uk/2009/01/29/for-vs-foreach-on-arrays-and-lists/

    根据文章,性能是这样的:

    ============ int[] ============
    For                 1.00
    ForHoistLength      2.03
    ForEach             1.36
    IEnumerableForEach 15.22
    Enumerable.Sum     15.73
    
    ============ List<int> ============
    For                 2.82
    ForHoistLength      3.49
    ForEach             4.78
    IEnumerableForEach 25.71
    Enumerable.Sum     26.03
    

    结果可以像 int 数组一样量化,for 循环的速度要快 2.8 倍。如果您知道数组的大小及其固定值,请使用 Array,否则使用 List。

    这是另一个链接:Performance of Arrays vs. Lists

    此外,对于大数据,请远离 Linq,并使用 for/foreach 循环。

    【讨论】:

    • 我知道数组会比列表更好,比较更多的是关于 int 列表与 bool 数组,其中数组中的索引充当“int”,值是条件。
    • 结果是对数组或列表求和,而不是查找时间。虽然通常我希望数组比列表更快。
    • 如果您今天重新运行基准测试会很好,因为在过去十年中发生了很大变化。
    • the comparison is more about an int list vs a bool array 你原来的问题@FanusduToit ,其中数组是 int 数组而不是 bool 数组,可能会让大多数读者(包括 Guaravsa 和我自己)感到困惑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    相关资源
    最近更新 更多