在数组上映射后调用排序

Calling sort after map on a array

我想在删除空格后按行长度对从 stdin 读取的行进行排序。代码按预期工作。

import std.algorithm, std.array, std.stdio, std.string;

void main()
{
    stdin
        .byLineCopy
        .map!(strip)
        .array
        .sort!((a, b) => a.length < b.length)
        .each!writeln;
}

但是,如果我将 map 行与 array 行交换,

void main()
{
    stdin
        .byLineCopy
        .array
        .map!(strip)
        .sort!((a, b) => a.length < b.length)
        .each!writeln;
}

程序编译失败,出现如下错误,

sort_lines.d(9): Error: template std.algorithm.sorting.sort cannot deduce function from argument types !((a, b) => a.length < b.length)(MapResult!(strip, string[])), candidates are:
/usr/include/dmd/phobos/std/algorithm/sorting.d(1852):        std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable && hasAssignableElements!Range) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)
Failed: ["/usr/bin/dmd", "-v", "-o-", "sort_lines.d", "-I."]

我不明白为什么。 map 函数不是应用于一个范围内的每个元素和 return 一个新范围吗?根据文档,sort 要求其范围参数是可随机访问的。是这个原因吗?如果是这样,由 map 编辑的范围 return 的类型是什么?

map returns 一个没有可分配或可交换元素的范围 - sort 指定的另一个要求。与您的第一个示例一样,解决方案是首先迭代到一个数组。

元素不可赋值,因为 map 进行计算而不是 return 引用的值。因此,即使您确实获取了 returned 元素的地址,并用该位置的新值覆盖它,它也不会更改实际后备数组中的值。

问题其实比这个稍微严重一点。 [1,2,3].map!(a => a * 2) 所做的是它从 [1,2,3] 中取出一个元素并将其乘以 2。如果我做了类似 [1,2,3].map!(a => a * 2)[0] = 4 的操作,则必须将函数 a => a * 2 反转为找出要放入 [1,2,3] 的值,并将其转换为 [2,2,3]。在上面的例子中,这相对容易,但如果我尝试分配 5 而不是 4 呢?如果映射函数是单向哈希怎么办?正如我们所见,唯一真正的解决方案是使用 mapped 值的存储 - 即 [1,2,3].map.array.