【问题标题】:Swift extension for [String]?[String] 的 Swift 扩展?
【发布时间】:2016-07-23 19:19:05
【问题描述】:

我正在尝试为[String] 编写扩展方法。

看起来你不能直接扩展[String](“类型'元素'被限制为非协议类型'字符串'”),虽然我遇到了这个技巧:

protocol StringType { }
extension String: StringType { }

但我仍然不能让 Swift 类型系统对此感到满意:

extension Array where Element: StringType {
    // ["a","b","c","d","e"] -> "a, b, c, d, or e".
    func joinWithCommas() -> String {
        switch count {
        case 0, 1, 2:
            return joinWithSeparator(" or ")
        default:
            return dropLast(1).joinWithSeparator(", ") + ", or " + last!
        }
    }
}

joinWithSeparator 调用是“模棱两可的”。我已经尝试了所有我能想到的方法,比如使用 (self as! [String])(以及一堆类似的变体),但似乎没有任何效果。

如何让 Swift 编译器对此感到满意?

【问题讨论】:

    标签: swift


    【解决方案1】:

    编辑/更新

    Swift 4 或更高版本最好将集合元素限制为 StringProtocol,它也将涵盖 Substrings。

    extension BidirectionalCollection where Element: StringProtocol {
        var joinedWithCommas: String {
            guard let last = last else { return "" }
            return count > 2 ? dropLast().joined(separator: ", ") + ", or " + last : joined(separator: " or ")
        }
    }
    

    如果所有元素都只是字符,我们可以简单地扩展 StringProtocol:

    extension StringProtocol {
        func joined(with separator: String = ",", conector: String = "") -> String {
            guard let last = last else { return "" }
            if count > 2 {
                return dropLast().map(String.init).joined(separator: separator + " ") + separator + " " + conector + " " + String(last)
            }
            return map(String.init).joined(separator: " " + conector + " ")
        }
    }
    

    let elements = "abc"
    let elementsJoined = elements.joined()                   // "a, b, c"
    let elementsSeparated = elements.joined(conector: "or")  // "a, b, or c"
    let elementsConected = elements.joined(conector: "and")  // "a, b, and c"
    


    原答案

    Swift 3.1 (Xcode 8.3.2) 中,您可以简单地将 Array 约束元素类型扩展为 String

    extension Array where Element == String {
        var joinedWithCommas: String {
            guard let last = last else { return "" }
            return count > 2 ? dropLast().joined(separator: ", ") + ", or " + last : joined(separator: " or ")
        }
    }
    

    ["a","b","c"].joinedWithCommas    // "a, b, or c"
    

    【讨论】:

    • 我们很快就会说 .. “记住过去我们不得不...” :)
    【解决方案2】:

    您可以按照joinWithSeparator 的声明(Cmd 单击它),发现它被定义为协议SequenceType 的扩展,而不是Array 类型。

    // swift 2:
    extension SequenceType where Generator.Element == String {
        public func joinWithSeparator(separator: String) -> String
    }
    

    (注意:在 Xcode 8 / Swift 3 中,如果您 Cmd 并单击 join(separator:),即使它是 still implemented inside Sequence,您也会到达 Array,但这不会使想法如下)

    我们可以对你的函数做同样的事情,我们扩展了 Array 采用的协议而不是 Array 本身:

    // swift 2:
    extension CollectionType where
            Generator.Element == String,
            SubSequence.Generator.Element == String,
            Index: BidirectionalIndexType
    {
        func joinWithCommas() -> String {
            switch count {
            case 0, 1, 2:
                return joinWithSeparator(" or ")
            default:
                return dropLast(1).joinWithSeparator(", ") + ", or " + last!
            }
        }
    }
    
    // swift 3:
    extension BidirectionalCollection where
            Iterator.Element == String,
            SubSequence.Iterator.Element == String
    {
        func joinWithCommas() -> String {
            switch count {
            case 0, 1, 2:
                return joined(separator: " or ")
            default:
                return dropLast().joined(separator: ", ") + ", or " + last!
            }
        }
    }
    

    注意:

    • 我们扩展CollectionType 以便能够使用count
    • 我们约束Generator.Element == String 使用joinWithSeparator
    • 我们约束SubSequence.Generator.Element == String 以确保dropLast(1) 可以使用joinWithSeparatordropLast(1) 返回关联类型 SubSequence
    • 我们限制@9​​87654339@ 使用last

    【讨论】:

    • 冗长。 POP有它的副作用。感谢您的解决方案✌️
    猜你喜欢
    • 2017-02-27
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多