本帖最后由 swifter 于 2016-9-5 18:29 编辑

今天的挑战题出自 Swift Users 邮件组的 Adriano Ferreira 。他的出发点是想要简化链式调用,但是很多情况下,想要使代码更 Swifter ,仅仅依靠看起来漂亮的链式语法是不够的,如Swifthumb上《详解Swift中Optional》第5项介绍的“Optional Chaining”:

Optional Chaining,如同名字一样,我们可以通过一个链来安全的访问一个Optional的属性或者方法。


简化Swift链式调用 Make it Swifter Challenge

简化Swift链式调用 Make it Swifter Challenge - 敏捷大拇指 - 简化Swift链式调用 Make it Swifter Challenge


我们回过头来认真看看Adriano Ferreira的思路:

[Swift] 纯文本查看 复制代码
func selectionSort(_ array: [Int]) -> [Int] {

    guard array.count > 1, let minElement = array.min() else {
        return array
    }

    let indexOfMinElement = array.index(of: minElement)!

    // All of this just to filter out the first smallest element and return the rest
    // Also tried ‘suffix(from:)' here, but couldn’t make it work properly
    let rest = array.enumerated()
                    .filter({ index, _ in index != indexOfMinElement })
                    .map({ _, element in element })

    return [minElement] + selectionSort(rest)
}





如何使其更 Swifter

首先,实用性。即使对于零个或一个元素的数组,我不认为添加代码去测试这些条件是实用的。我认为让代码直接顺序执行是更好的选择,即使这样对于只有一个元素的情况不是特别完美。

其次,连贯性。我不喜欢先找到最小值,然后再去找它的索引的想法。而枚举是允许将这两个操作串联起来的。

第三,风格。数组的遍历应该返回元组类型 (index: Index, value: Element)。但是示例并没有这么做,所以我想要借此机会来扩展数组,使其支持这种类型的元组。同时,我的方案比他需要的答案更复杂一些,因为我想要使用$0.value与 $1.index,而不是使用$0.1和$1.0。

我重新设计的代码在这里(如下),请你也分享你的那一份吧!

[Swift] 纯文本查看 复制代码
/// An indexed tuple specifically for use with enumerated results
public typealias Indexed<Index, Value> = (index: Index, value: Value)

public extension Array {

    /// Establishes a lazy sequence of enumerated items using index and value labels
    public func indexed() -> LazyMapSequence<EnumeratedSequence<[Element]>, Indexed<Index, Element>> {
        return enumerated()
            .lazy
            .map({ return $0 as Indexed<Index, Element> })
    }

}

/// Perform a simple selection sort
///
/// "Selection sort is noted for its simplicity, and it has performance 
/// advantages over more complicated algorithms in certain situations, 
/// particularly where auxiliary memory is limited."
///
/// - Complexity: O(count^2)
/// - Reference: [[url=https://en.wikipedia.org/wiki/Selection_sort]https://en.wikipedia.org/wiki/Selection_sort[/url]]([url=https://en.wikipedia.org/wiki/Selection_sort]https://en.wikipedia.org/wiki/Selection_sort[/url])
///
func selectionSort(_ array: [Int]) -> [Int] {
    guard let minElement = array
        .indexed()
        .min(isOrderedBefore: { $0.value < $1.value })
        else { return [] }
    var array = array // mutable shadow
    array.remove(at: minElement.index)
    return [minElement.value] + selectionSort(array)
}

let x = [1, 3, 5, 2, 4, 9, 8, -5, 6, 4]
print(selectionSort(x)) // [-5, 1, 2, 3, 4, 4, 5, 6, 8, 9]
print(selectionSort([2])) // [2]
print(selectionSort([])) // []





作者:Martin_Joy