接上篇 Array(一) 扩展归纳,继续记录其他常用的扩展
9、 String 数组扩展
// MARK: - String 数组扩展
extension Array where Element == String {
/// 转换为字符串(用分隔符连接)
func toString(separator: String = ", ") -> String {
return joined(separator: separator)
}
/// 过滤空字符串
var nonEmpty: [String] {
return filter { !$0.isEmpty }
}
/// 过滤空白字符串
var nonBlank: [String] {
return filter { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
}
/// 转换为小写
var lowercased: [String] {
return map { $0.lowercased() }
}
/// 转换为大写
var uppercased: [String] {
return map { $0.uppercased() }
}
/// 去除首尾空白字符
var trimmed: [String] {
return map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
}
}
// 生成十六进制字符串
extension Array where Element == UInt8 {
var hexString: String {
return self.compactMap { String(format: "%02x", $0).uppercased() }
.joined(separator: "")
}
}
使用示例:
// MARK: - 1. toString - 转换为字符串
print("=== 1. toString - 字符串连接 ===")
let fruits = ["苹果", "香蕉", "橙子", "葡萄"]
print("水果数组: \(fruits)")
print("默认连接 (逗号): \(fruits.toString())")
print("自定义分隔符 (|): \(fruits.toString(separator: " | "))")
print("换行连接: \(fruits.toString(separator: "\n"))")
// MARK: - 2. nonEmpty - 过滤空字符串
print("=== 2. nonEmpty - 过滤空字符串 ===")
let userInputs = ["张三", "", "李四", "", "王五", "", "赵六"]
print("原始输入: \(userInputs)")
print("过滤空字符串后: \(userInputs.nonEmpty)")
print("有效用户数量: \(userInputs.nonEmpty.count)")
// MARK: - 3. nonBlank - 过滤空白字符串
print("=== 3. nonBlank - 过滤空白字符串 ===")
let comments = ["很好用!", " ", "推荐给朋友", "\n\n", " ", "五星好评", "\t\t"]
print("用户评论原始数据:")
for (index, comment) in comments.enumerated() {
print(" \(index + 1): '\(comment)'")
}
print("\n过滤空白后:")
let validComments = comments.nonBlank
for (index, comment) in validComments.enumerated() {
print(" \(index + 1): '\(comment)'")
}
print("有效评论数: \(validComments.count)")
// MARK: - 4. lowercased - 转换为小写
print("=== 4. lowercased - 转换为小写 ===")
let mixedCaseNames = ["iPhone", "MacBook", "iPad", "Apple Watch", "AirPods"]
print("原始产品名: \(mixedCaseNames)")
print("小写转换: \(mixedCaseNames.lowercased)")
// MARK: - 5. uppercased - 转换为大写
print("=== 5. uppercased - 转换为大写 ===")
let countryNames = ["china", "usa", "japan", "germany", "france"]
print("国家名称: \(countryNames)")
print("大写转换: \(countryNames.uppercased)")
// MARK: - 6. trimmed - 去除首尾空白字符
print("=== 6. trimmed - 去除首尾空白字符 ===")
let userNames = [" 张三 ", "\n李四\n", "\t王五\t", " 赵六 ", "孙七"]
print("用户姓名输入:")
for (index, name) in userNames.enumerated() {
print(" \(index + 1): '\(name)'")
}
let cleanNames = userNames.trimmed
print("\n清理后:")
for (index, name) in cleanNames.enumerated() {
print(" \(index + 1): '\(name)'")
}
// MARK: - 7. 综合应用示例
print("=== 7. 综合应用示例 ===")
// 标签系统
print("\n🏷️ 文章标签系统:")
let articleTags = [" iOS ", "", " SWIFT ", " mobile ", "\n\n", " Development ", " "]
print("原始标签: \(articleTags)")
let processedTags = articleTags
.trimmed // 去空白
.nonEmpty // 去空字符串
.lowercased // 统一小写
.map { $0.capitalized } // 首字母大写
print("处理后标签: \(processedTags)")
print("标签字符串: #\(processedTags.toString(separator: " #"))")
print("SEO标签: \(processedTags.lowercased.toString(separator: ", "))")
10、实用扩展
// MARK: - 实用扩展
extension Array {
/// 判断数组是否为空或nil
var isNilOrEmpty: Bool {
return isEmpty
}
/// 安全的count(防止nil)
var safeCount: Int {
return count
}
/// 转换为JSON字符串(如果元素可序列化)
func toJSONString() -> String? {
guard JSONSerialization.isValidJSONObject(self) else { return nil }
guard let data = try? JSONSerialization.data(withJSONObject: self, options: []) else { return nil }
return String(data: data, encoding: .utf8)
}
/// 打印数组内容(调试用)
func printElements() {
for (index, element) in enumerated() {
print("[\(index)]: \(element)")
}
}
/// 执行每个元素的操作
func forEach(_ body: (Element, Int) throws -> Void) rethrows {
for (index, element) in enumerated() {
try body(element, index)
}
}
/// 异步处理每个元素
@available(iOS 13.0, *)
func asyncForEach(_ operation: @escaping (Element) async -> Void) async {
for element in self {
await operation(element)
}
}
/// 条件追加元素
mutating func appendIf(_ condition: Bool, _ element: Element) {
if condition {
append(element)
}
}
/// 条件追加数组
mutating func appendIf(_ condition: Bool, contentsOf array: [Element]) {
if condition {
append(contentsOf: array)
}
}
}
使用示例:
// MARK: - 1. isNilOrEmpty - 判断数组是否为空
print("=== 1. isNilOrEmpty - 空数组判断 ===")
let emptyArray: [Int] = []
let nonEmptyArray = [1, 2, 3]
print("空数组 \(emptyArray) 是否为空: \(emptyArray.isNilOrEmpty ? "✅" : "❌")")
print("非空数组 \(nonEmptyArray) 是否为空: \(nonEmptyArray.isNilOrEmpty ? "❌" : "✅")")
// MARK: - 3. toJSONString - JSON序列化
print("=== 3. toJSONString - JSON序列化 ===")
// 嵌套数组
let nestedArray = [
["name": "张三", "age": 25],
["name": "李四", "age": 30]
]
print("\n嵌套数组序列化:")
if let json = nestedArray.toJSONString() {
print(" 成功: \(json)")
} else {
print(" 失败 ❌")
}
// 实际应用:API数据发送
print("\n📡 API数据发送示例:")
let userData = [
"用户ID": 12345,
"用户名": "developer",
"邮箱": "dev@example.com"
] as [String: Any]
let userArray = [userData]
if let jsonString = userArray.toJSONString() {
print("准备发送的JSON: \(jsonString)")
print("数据大小: \(jsonString.count) 字符")
}
// MARK: - 4. printElements - 调试打印
print("=== 4. printElements - 调试打印 ===")
let debugArray = ["启动", "加载配置", "连接数据库", "初始化完成"]
print("应用启动流程调试:")
debugArray.printElements()
// MARK: - 5. forEach (带索引) - 增强遍历
print("=== 5. forEach (带索引) - 增强遍历 ===")
let students = ["张三", "李四", "王五", "赵六"]
print("学生名单:")
students.forEach { name, index in
let number = index + 1
print(" \(number). \(name)")
}
// MARK: - 6. asyncForEach - 异步处理
let urls = [
"https://api.github.com/users/apple",
"https://api.github.com/users/microsoft",
"https://api.github.com/users/google"
]
print("开始处理 \(urls.count) 个URL...")
await urls.asyncForEach { url in
await downloadUserInfo(from: url)
}
print("所有网络请求完成!\n")
// MARK: - 7. appendIf - 条件追加
print("=== 7. appendIf - 条件追加 ===")
var shoppingCart = ["苹果", "香蕉"]
print("购物车初始状态: \(shoppingCart)")
let hasDiscount = true
let isVip = false
shoppingCart.appendIf(hasDiscount, "优惠券")
print("有折扣,添加优惠券: \(shoppingCart)")
shoppingCart.appendIf(isVip, "VIP专享商品")
print("非VIP,不添加专享商品: \(shoppingCart)")
// 批量条件追加
print("\n批量条件追加:")
var features: [String] = ["基础功能"]
let isPremium = true
let isEnterprise = false
let premiumFeatures = ["高级统计", "数据导出", "API访问"]
let enterpriseFeatures = ["单点登录", "自定义品牌", "专属支持"]
features.appendIf(isPremium, contentsOf: premiumFeatures)
print("Premium用户功能: \(features)")
features.appendIf(isEnterprise, contentsOf: enterpriseFeatures)
print("非Enterprise用户,功能不变: \(features)")
11、搜索和过滤扩展
// MARK: - 搜索和过滤扩展
extension Array where Element: StringProtocol {
/// 模糊搜索 - 检查查询字符是否按顺序出现在字符串中
func fuzzySearch(_ query: String) -> [Element] {
guard !query.isEmpty else { return Array(self) }
let lowercaseQuery = query.lowercased()
return filter { element in
let elementString = String(element).lowercased()
var queryIndex = lowercaseQuery.startIndex
for char in elementString {
if queryIndex < lowercaseQuery.endIndex &&
char == lowercaseQuery[queryIndex] {
queryIndex = lowercaseQuery.index(after: queryIndex)
}
// 如果所有查询字符都匹配了,提前退出
if queryIndex == lowercaseQuery.endIndex {
break
}
}
return queryIndex == lowercaseQuery.endIndex
}
}
/// 按相关性排序的搜索
func search(_ query: String) -> [Element] {
let lowercaseQuery = query.lowercased()
return self
.filter { $0.lowercased().contains(lowercaseQuery) }
.sorted { left, right in
let leftLower = left.lowercased()
let rightLower = right.lowercased()
// 优先级:完全匹配 > 开头匹配 > 包含匹配
if leftLower == lowercaseQuery { return true }
if rightLower == lowercaseQuery { return false }
if leftLower.hasPrefix(lowercaseQuery) && !rightLower.hasPrefix(lowercaseQuery) { return true }
if rightLower.hasPrefix(lowercaseQuery) && !leftLower.hasPrefix(lowercaseQuery) { return false }
return leftLower.count < rightLower.count
}
}
}
12、 性能监控扩展
// MARK: - 性能监控扩展
extension Array {
/// 性能基准测试
func benchmark<T>(
iterations: Int = 1000,
operation: (Array<Element>) -> T
) -> (averageTime: TimeInterval, results: [T]) {
var times: [TimeInterval] = []
var results: [T] = []
for _ in 0..<iterations {
let startTime = CFAbsoluteTimeGetCurrent()
let result = operation(self)
let endTime = CFAbsoluteTimeGetCurrent()
times.append(endTime - startTime)
results.append(result)
}
let averageTime = times.reduce(0, +) / TimeInterval(times.count)
return (averageTime, results)
}
/// 内存使用情况
var memoryFootprint: Int {
return MemoryLayout<Element>.stride * count + MemoryLayout<Array<Element>>.size
}
/// 性能分析报告
func performanceReport() -> String {
let elementSize = MemoryLayout<Element>.size
let arraySize = MemoryLayout<Array<Element>>.size
let totalMemory = elementSize * count + arraySize
return """
Array Performance Report:
- Element count: \(count)
- Element size: \(elementSize) bytes
- Array overhead: \(arraySize) bytes
- Total memory: \(totalMemory) bytes
- Memory per element: \(count > 0 ? totalMemory / count : 0) bytes
"""
}
}
使用示例:
-- 性能基准测试示例
let numbers = Array(1...10000)
// 测试不同操作的性能
print("数组大小: \(numbers.count) 个元素")
// 测试求和操作
let sumBenchmark = numbers.benchmark(iterations: 1000) { array in
return array.reduce(0, +)
}
print("\n求和操作基准测试:")
print(" 平均耗时: \(String(format: "%.6f", sumBenchmark.averageTime * 1000))毫秒")
print(" 首个结果: \(sumBenchmark.results.first ?? 0)")
// MARK: -- 内存分析示例
// 不同大小的数组内存对比
let smallArray = Array(1...100)
let mediumArray = Array(1...1000)
let largeArray = Array(1...10000)
print("内存使用对比:")
print(" 小数组 (100元素): \(smallArray.memoryFootprint) 字节")
print(" 中数组 (1000元素): \(mediumArray.memoryFootprint) 字节")
print(" 大数组 (10000元素): \(largeArray.memoryFootprint) 字节")
// 计算内存增长比例
let smallToMedium = Double(mediumArray.memoryFootprint) / Double(smallArray.memoryFootprint)
let mediumToLarge = Double(largeArray.memoryFootprint) / Double(mediumArray.memoryFootprint)
print("\n内存增长比例:")
print(" 小→中: \(String(format: "%.1f", smallToMedium))倍")
print(" 中→大: \(String(format: "%.1f", mediumToLarge))倍")
// MARK: -- 性能分析报告示例"
// 不同类型数组的性能报告
let intArray = Array(1...5000)
let stringArray = Array(repeating: "Hello World", count: 5000)
print("Int数组性能报告:")
print(intArray.performanceReport())
print("\nString数组性能报告:")
print(stringArray.performanceReport())
// 性能对比分析
print("\n🔍 性能对比分析:")
let intMemory = intArray.memoryFootprint
let stringMemory = stringArray.memoryFootprint
print(" 相同元素数量下的内存使用:")
print(" Int: \(intMemory) 字节")
print(" String: \(stringMemory) 字节 (\(String(format: "%.1f", Double(stringMemory)/Double(intMemory)))倍)")
暂时记录在这里,后续有新增的再补充吧。