Замена нескольких вхождений в массиве - Swift 4.1 - PullRequest
0 голосов
/ 25 апреля 2018

Замена нескольких вхождений в массиве

Swift 4.1, Xcode 9.3

Я хочу сделать расширение аналогично расширению, которое я сделал для Array для String.


Расширение строки:

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]

Как мне достичь этого идеала (желательно наиболее эффективным способом)?

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018
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
  }
}
0 голосов
/ 30 апреля 2018

Если элементы массива 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 элементов, это можно реализовать кратко, используя map и first(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 }
    }
}
0 голосов
/ 25 апреля 2018

Я думаю, вы должны использовать оператор 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)
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...