首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >D minMax函数实现

D minMax函数实现
EN

Code Review用户
提问于 2018-06-18 20:34:16
回答 1查看 59关注 0票数 3

我碰巧需要同时找到数组的最大值和最小值,所以我决定在D中实现一个minMax函数。

问题:

  1. 这是一个有效的实现吗?
  2. 有可读性吗?
  3. 如有任何一般性反馈,将不胜感激。

谢谢!

代码语言:javascript
复制
import std.range;
import std.traits;
import std.typecons;
import std.functional;

class EmptyContainerException : Exception {
    this(string msg, string file = __FILE__, size_t line = __LINE__) {
        super(msg, file, line);
    }
}

// returns a tuple containing the minimum and maximum elements of a finite InputRange
template minMax(alias pred = "a") {
    alias map = unaryFun!pred;

    auto minMax(Range)(Range r)
    if(isInputRange!Range && !isInfinite!Range && is(typeof(map(r.front)))) {
        if(r.empty) {
            throw new EmptyContainerException(
                "minMax expected a container with at least 1 element, got an empty container."
            );
        }
        auto front = r.front;
        auto frontMap = map(front);

        auto min = front;
        auto max = front;
        auto minMap = frontMap;
        auto maxMap = frontMap;

        r.popFront;
        while(!r.empty) {
            front = r.front;
            frontMap = map(front);
            if(frontMap > maxMap) {
                max = front;
                maxMap = frontMap;
            }
            if(frontMap < minMap) {
                min = front;
                minMap = frontMap;
            }
            r.popFront;
        }
        return tuple!("min", "max")(min, max);
    }
}

unittest {
    import std.exception : assertThrown;

    int[] test1 = [1, 2, 3, 4, 5];
    auto test1result = test1.minMax;
    assert(test1result.min == 1 && test1result.max == 5);

    string test2 = "Hello, World!";
    auto test2result = test2.minMax;
    assert(test2result.min == ' ' && test2result.max == 'r');

    int[] test3 = [];
    assertThrown!EmptyContainerException(test3.minMax);

    string[] test4 = ["who", "is", "the", "longest", "word"];
    auto test4result = test4.minMax!"a.length";
    assert(test4result.min == "is" && test4result.max == "longest");
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2018-06-19 07:05:31

这是一个有效的实现吗?

是啊。它精确地每项调用一次map,否则只执行常规的范围调用。在某些情况下,专门的实现可能更高效(但可能只在使用向量指令的情况下),并行实现也是如此,但这两种实现都不像代码那样具有通用性。

有可读性吗?

当然,这是我见过的最易读的代码之一。循环的内容有些密集。你也许可以让它不像这样密集:

代码语言:javascript
复制
    auto front = tuple!("elem", "map")(r.front, map(r.front));
    auto min = front;
    auto max = front;

    r.popFront;
    foreach (e; r) {
        front = tuple(e, map(e));
        if(front.map > max.map) max = front;
        if(front.map < min.map) min = front;
    }
    return tuple!("min", "max")(min.elem, max.elem);

除此之外,我什么都没有。

如有任何一般性反馈,将不胜感激。

正如上面一节所暗示的那样,您可能希望使用while (!empty)而不是foreach。这将您的代码减少一行(r.popFront()),并使您更清楚地知道,您将遍历范围中的每个元素。它不应该以任何方式改变代码的性能。

您应该在模板上添加一个if (is(typeof(unaryFun!pred)))约束,这样函数的用户就会在他或她试图用arr.minMax!"invalid string"实例化它的行上得到一条错误消息。

另外,pred的名称是错误的-- 谓词是布尔值函数,如equalsame colorcontains bees.我叫它FnFun

作为次要的nit,我还会将map的名称更改为fnfun (注意大写的不同)。这是因为我一直把你的mapstd.algorithm.map混为一谈。这个概念是正确的,但本质上这个名字已经被取走了。

总之,非常好-我唯一的评论基本上是吹毛求疵。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/196771

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档