替换数组中的多次出现 - 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
我想制作一个类似于我为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]
我如何实现这个理想(最好以最有效的方式)?
【问题讨论】:
【参考方案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
元素的数组,可以实现
简洁地使用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
【讨论】:
【参考方案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的主要内容,如果未能解决你的问题,请参考以下文章
通过正则表达式模式匹配使用 stringbuilder 替换多次出现的字符串
Oracle REGEXP_REPLACE - 用子字符串替换多次出现的模式