代码之家  ›  专栏  ›  技术社区  ›  Tempestas Ludi

以与函数式编程兼容的方式交换c中的数组键和值

  •  0
  • Tempestas Ludi  · 技术社区  · 8 年前

    假设我有以下C代码:

    var array = new []{3, 2, 5, 4, 1, 0};
    var converted = new int[array.Length];
    for (var i = 0; i < array.Length; i++) {
        converted[array[i]] = i;
    }
    

    最后,我们 converted == new {5, 4, 1, 0, 3, 2}; 是的。然而,“因为循环是邪恶的”,所以我可以重写如下:

    var array = new []{3, 2, 5, 4, 1, 0};
    var converted = new int[array.Length];
    array
        .Select((value, index) => new {index, value})
        .ToList()
        .ForEach(o => converted[o.value] = o.index);
    

    然而,我们仍然有一个变异的状态。LINQ提供了一个很好的方法来做到这一点,而不增加渐近复杂性吗?

    我知道我可以根据这些值进行排序,或者使用某种搜索技术,但是在这两种情况下,复杂性变得 O(n log n) 或者更多。

    编辑:我知道至少第二个是丑陋的。第一种是这些类型的事情通常是如何完成的,但是在几乎所有情况下,linq都提供了一种比for循环更好、更易于理解的方式。因此,我想知道是否有办法这样做与林肯。

    1 回复  |  直到 8 年前
        1
  •  1
  •   Sweeper    8 年前

    你的for循环是 好的 是的。不要改变它。有时最好是按程序办事,而其他时候则最好是按功能办事。在这种情况下,程序性更好。

    看看如果从功能上做的话会有多糟糕:

    // assuming the values are all members of the set of natural numbers from 0 to (array.Length - 1)
    var converted = array.Select((x, i) => new { Index = i, Element = x })
                         .OrderBy(x => x.Element)
                         .Select(x => x.Index).ToList();
    

    这比程序版本可读性差得多。