替换数组中的多次出现 - Swift 4.1

Posted

技术标签:

【中文标题】替换数组中的多次出现 - Swift 4.1【英文标题】:Replacing Multiple Occurrences in Array - Swift 4.1 【发布时间】:2018-10-06 03:52:42 【问题描述】:

替换数组中的多次出现

Swift 4.1,Xcode 9.3

我想制作一个类似于我为ArrayString 制作的扩展。


字符串扩展:

public extension String 
    
    ///
    /// Replaces multiple occurences of strings/characters/substrings with their associated values.
    /// ````
    /// var string = "Hello World"
    /// let newString = string.replacingMultipleOccurrences(using: (of: "l", with: "1"), (of: "o", with: "0"), (of: "d", with: "d!"))
    /// print(newString) //"He110 w0r1d!"
    /// ````
    /// 
    /// - Returns:
    /// String with specified parts replaced with their respective specified values.
    /// 
    /// - Parameters:
    ///     - array: Variadic values that specify what is being replaced with what value in the given string 
    ///
    public func replacingMultipleOccurrences<T: StringProtocol, U: StringProtocol>(using array: (of: T, with: U)...) -> String 
        var str = self
        for (a, b) in array 
            str = str.replacingOccurrences(of: a, with: b)
        
        return str
    


用法:

var string = "Hello World"
let newString = string.replacingMultipleOccurrences(using: (of: "l", with: "1"), (of: "o", with: "0"), (of: "d", with: "d!"))
print(newString) //"He110 w0r1d!"

到目前为止我对数组的相同尝试

public extension Array 
    public func replacingMultipleOccurrences(using array: (of: Element, with: Element)...) -> Array 
        
        var newArr : Array<Element> = self
        var arr = array.filter  (arg) -> Bool in
            let (a, b) = arg
            return newArr.contains(a)
                  
        for (i,e) in self.enumerated() 
            for (a,b) in arr 
                if e == a 
                    newArr[i] = b
                
            
        
        return newArr
    

注意: 目前,此扩展程序正在产生大量错误。

理想用法:

let arr = [1,2,3,4,5,6,7,8,9]
let newArr = arr.replacingMultipleOccurrences(using: (of: 2, with: 20), (of: 3, with: 30), (of: 5, with: 50), (of: 8, with: 80), (of: 9, with: 90))
print(newArr) //[1,20,30,4,50,6,7,80,90]

我如何实现这个理想(最好以最有效的方式)?

【问题讨论】:

【参考方案1】:
extension Array where Element: Equatable 
func replacingMultipleOccurrences(using array: (of: Element, with: Element)...) -> Array 
    var newArr: Array<Element> = self

    for replacement in array 
        for (index, item) in self.enumerated() 
            if item == replacement.of 
                newArr[index] = replacement.with
            
        
    

    return newArr
  

【讨论】:

请注意,[1, 2, 3].replacingMultipleOccurrences(using: (of: 2, with: 3), (of: 3, with: 4)) 会使用这种方法返回 [1, 4, 4],这可能是出乎意料的。 这不应该符合Equatable而不是Comparable吗?【参考方案2】:

如果数组元素是Hashable,那么我将创建一个替换 字典。然后可以有效地完成替换 单次遍历(使用map)和(快速)字典查找:

public extension Array where Element: Hashable 
    public func replacingMultipleOccurrences(using array: (of: Element, with: Element)...) -> Array 

        let replacements = Dictionary<Element, Element>(array, uniquingKeysWith:  $1 )
        return map  replacements[$0] ?? $0 
    

如果替换值恰好是 替换表后面的替换键。 示例:

let arr = [1, 2, 3, 2, 1]
let newArr = arr.replacingMultipleOccurrences(using: (of: 2, with: 3), (of: 3, with: 4))
print(newArr) // [1, 3, 4, 3, 1]

对于只有 Equatable 元素的数组,可以实现 简洁地使用mapfirst(where:)

public extension Array where Element: Equatable 
    public func replacingMultipleOccurrences(using array: (of: Element, with: Element)...) -> Array 

        return map  elem in array.first(where:  $0.of == elem )?.with ?? elem 
    

【讨论】:

【参考方案3】:

我认为你应该使用map 运算符。

extension String 
    func replace(mapping : [String : String]) -> String 
        return self.map  char -> String in  
            if let newValue = mapping[String(char)] 
                return newValue
             else 
                return String(char)
            
        
    

【讨论】:

你应该在这里扩展数组 a String 是一个 char 数组 :) 此扩展产生错误:Cannot convert return expression of type '[String]' to return type 'String' 这也不起作用,因为你不能用这个替换整个单词的出现。 @NoahWilder 这不是必需的

以上是关于替换数组中的多次出现 - Swift 4.1的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 正则表达式替换用逗号包围的字符串的多次出现

sed 用多次出现的单词替换单词分隔符

通过正则表达式模式匹配使用 stringbuilder 替换多次出现的字符串

Oracle REGEXP_REPLACE - 用子字符串替换多次出现的模式

Regexp_Replace 在 Oracle 中多次出现具有相同替换次数的字符

获取数组中的所有非唯一值(即:重复/多次出现)