微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

通过在 Swift 中混合元素将多个数组合并为一个数组?

如何解决通过在 Swift 中混合元素将多个数组合并为一个数组?

示例:

let a = [a1,a2,a3]
let b = [b1,b2]
let c = [c1,c2,c3,c4]

我需要以下结果:

[a1,b1,c1,b2,a3,c4]

a1,... - 任何相同类型的对象

我目前的解决方案是创建这些数组的可变副本,并按指定顺序在每个数组上依次调用 popFirst,直到所有数组都变空。

但是是否有可能通过使用 Swift 的内部特性而不需要手动迭代来解决这个任务?例如像下面的代码

[a,b,c].map { ... }.filter { ... }.reduce ...

解决方法

这是一个使用基本 for 循环的解决方案,但它在可以合并的数组数量方面很灵活

func merge<T>(_ arrays: [T]...) -> [T] {
    guard let longest = arrays.max(by: { $0.count < $1.count })?.count else { return [] }
    var result = [T]()
    for index in 0..<longest {
        for array in arrays {
            guard index < array.count else { continue }
            result.append(array[index])
        }
    }
    return result
}

问题示例

print(merge(a,b,c))

["a1","b1","c1","a2","b2","c2","a3","c3","c4"]

,

将此视为“转置”二维数组 [a,c],除非没有元素,否则您只需忽略它并继续。这让我想起了 this question of mine,只是您希望内部数组具有不同的大小。

我们可以通过查找具有最大 count 的内部数组来修改 Alexander 的答案以满足您的需求,并使用它而不是第一个内部数组。我们还将外部 map 更改为 flatMap,因为您希望它变平。

我们还引入了一个 safe: 下标,这样 compactMap 可以用来忽略那些“缺失”的元素。

extension Collection where Self.Element: RandomAccessCollection {
    
    func transposed() -> [Self.Element.Element] {
        guard let rowWithMaxElems = self.max(by: { $0.count < $1.count }) else { return [] }
        return rowWithMaxElems.indices.flatMap { index in
            self.compactMap { $0[safe: index] }
        }
    }
}

extension RandomAccessCollection {
    subscript(safe index: Index) -> Element? {
        get {
            indices.contains(index) ? self[index] : nil
        }
    }
}

let a = [1,2,3]
let b = [4,5]
let c = [6,7,8,9]

let result = [a,c].transposed()
print(result)
,

试试这个 -

let a = ["a1","a3"]
let b = ["b1","b2"]
let c = ["c1","c4"]
        
var d: [String] = []
let count = max(a.count,b.count,c.count)
for i in 0..<count {
    if i < a.count { d.append(a[i]) }
    if i < b.count { d.append(b[i]) }
    if i < c.count { d.append(c[i]) }
}
print(d)

输出 -

["a1","c4"]
,

你可以这样做

let a = ["a1","c4"]

let initArr = [a,c]
let maxCount = initArr.max(by: {$0.count < $1.count})?.count ?? 0

let newArr: [String] = (0..<maxCount).flatMap { (index) -> [String]in
    var arr: [String] = []
    _ = initArr.indices.map { (number)in
        if index < initArr[number].count {
            arr.append(initArr[number][index])
        }
    }
    return arr
}
print(newArr) // ["a1","c4"]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。