在数组上映射后调用排序

时间:2019-02-05 08:44:32

标签: d

在修剪掉空白后,我想按行长对从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."]

我不明白为什么。映射功能是否不适用于范围内的每个元素并返回新范围?根据文档,sort要求其range参数是可随机访问的。是这个原因吗?如果是这样,map返回的范围是什么类型?

1 个答案:

答案 0 :(得分:2)

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

元素不可分配,因为map会进行计算并且不会通过ref返回值。因此,即使您确实抓取了返回元素的地址,并用该位置的新值覆盖了该地址,它也不会更改实际后备数组中的值。

问题实际上比这还糟。 [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怎么办?如果映射函数是单向哈希怎么办?正如我们所看到的,唯一真正的解决方案是存储具有map个ped值的商店,即[1,2,3].map.array