在Swift中展平数组数组

时间:2014-06-28 09:03:00

标签: swift

在Scala,Xtend,Groovy,Ruby和co中,Swift中有一个对应flatten吗?

var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatten() // shall deliver [1,2,3,4,5,6,7,8,9] 

当然我可以使用reduce,但有点糟糕

var flattened = aofa.reduce(Int[]()){
    a,i in var b : Int[] = a
    b.extend(i)
    return b
}

14 个答案:

答案 0 :(得分:335)

Swift 3.0

<强> reduce

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = numbers.reduce([], +)

<强> flatMap

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = numbers.flatMap { $0 }

<强> joined

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let joined = Array(numbers.joined())

答案 1 :(得分:28)

在Swift标准库中,为符合Sequence协议的所有类型(或者在Swift 3之前SequenceType上的joined)实现了flatten函数,其中包括{{1} }}:

Array

在某些情况下,使用let numbers = [[1,2,3],[4],[5,6,7,8,9]] let flattened = Array(numbers.joined()) 可能是有益的,因为它返回一个惰性集合而不是一个新数组,但在传递给joined()初始化器时总是可以转换为数组,如上例所示

答案 2 :(得分:8)

Swift 4.x

只是增加数组的复杂度,如果存在包含数组数组的数组,那么flatMap实际上会失败。

假设数组为

var array:[Any] = [1,2,[[3,4],[5,6,[7]]],8]

flatMapcompactMap返回的内容是:

array.compactMap({$0})

//Output
[1, 2, [[3, 4], [5, 6, [7]]], 8]

为了解决这个问题,我们可以使用简单的for循环逻辑+递归

func flattenedArray(array:[Any]) -> [Int] {
    var myArray = [Int]()
    for element in array {
        if let element = element as? Int {
            myArray.append(element)
        }
        if let element = element as? [Any] {
            let result = flattenedArray(array: element)
            for i in result {
                myArray.append(i)
            }

        }
    }
    return myArray
}

因此使用给定的数组调用此函数

flattenedArray(array: array)

结果是:

[1, 2, 3, 4, 5, 6, 7, 8]

考虑到这里Int的情况,此函数将有助于展平任何类型的数组

游乐场输出: enter image description here

答案 3 :(得分:3)

这对我有用:

let numbers = [[1, 2, 3], [4, 5, 6]]
let flattenNumbers = numbers.reduce([], combine: +)

答案 4 :(得分:3)

Swift 4.x

foreach ($paxSafety as $key => $value) { $paxSafetyContent = new PaxSafety; $paxSafetyContent->paxsafety_image = $value; /** if a video with the current image index exists insert the video value **/ if(isset($paxSafetyVideo[$key]) && $paxSafetyVideo[$key]){ $paxSafetyContent->paxsafety_video = $paxSafetyVideo[$key]; } $paxSafetyContent->save(); } 的用法并未被弃用,这是为此而做的。 https://developer.apple.com/documentation/swift/sequence/2905332-flatmap

flatMap

答案 5 :(得分:2)

reduce的另一个更通用的实现,

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = reduce(numbers,[],+)

这可以完成同样的事情,但可以更深入地了解reduce中发生的事情。

来自Apple的文档,

func reduce<S : SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U) -> U

说明

依次将 combine 重复调用的结果与初始化为 initial 的累积值和 sequence 的每个元素一起返回。

答案 6 :(得分:1)

Swift 4.2

我在下面写了一个简单的数组扩展。您可以用来展平包含另一个数组或元素的数组。不像join()方法。

public extension Array {
    public func flatten() -> [Element] {
        return Array.flatten(0, self)
    }

    public static func flatten<Element>(_ index: Int, _ toFlat: [Element]) -> [Element] {
        guard index < toFlat.count else { return [] }

        var flatten: [Element] = []

        if let itemArr = toFlat[index] as? [Element] {
            flatten = flatten + itemArr.flatten()
        } else {
            flatten.append(toFlat[index])
        }

        return flatten + Array.flatten(index + 1, toFlat)
    }
}

用法:

let numbers: [Any] = [1, [2, "3"], 4, ["5", 6, 7], "8", [9, 10]]

numbers.flatten()

答案 7 :(得分:1)

修改了@RahmiBozdag的答案, 1.公共扩展中的方法是公共的。 2.删除了额外的方法,因为开始索引将始终为零。 3.我没有找到将compactMap放在nil和optionals里面的方法,因为在方法T里面总是[Any?],欢迎任何建议。

 let array = [[[1, 2, 3], 4], 5, [6, [9], 10], 11, nil] as [Any?]

 public extension Array {

 func flatten<T>(_ index: Int = 0) -> [T] {
        guard index < self.count else { 
            return [] 
        }

        var flatten: [T] = []

        if let itemArr = self[index] as? [T] {
            flatten += itemArr.flatten()
        } else if let element = self[index] as? T {
            flatten.append(element)
        }
        return flatten + self.flatten(index + 1)
   }

}

let result: [Any] = array.flatten().compactMap { $0 }
print(result)
//[1, 2, 3, 4, 5, 6, 9, 10, 11]

答案 8 :(得分:0)

您可以使用以下方法展平嵌套数组:

var arrays = [1, 2, 3, 4, 5, [12, 22, 32], [[1, 2, 3], 1, 3, 4, [[[777, 888, 8999]]]]] as [Any]

func flatten(_ array: [Any]) -> [Any] {

    return array.reduce([Any]()) { result, current in
        switch current {
        case(let arrayOfAny as [Any]):
            return result + flatten(arrayOfAny)
        default:
            return result + [current]
        }
    }
}

let result = flatten(arrays)

print(result)

/// [1, 2, 3, 4, 5, 12, 22, 32, 1, 2, 3, 1, 3, 4, 777, 888, 8999]

答案 9 :(得分:0)

Apple Swift版本5.1.2(swiftlang-1100.0.278 clang-1100.0.33.9)
目标:x86_64-apple-darwin19.2.0

Screenshot

let optionalNumbers = [[1, 2, 3, nil], nil, [4], [5, 6, 7, 8, 9]]
print(optionalNumbers.compactMap { $0 }) // [[Optional(1), Optional(2), Optional(3), nil], [Optional(4)], [Optional(5), Optional(6), Optional(7), Optional(8), Optional(9)]]
print(optionalNumbers.compactMap { $0 }.reduce([], +).map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(optionalNumbers.compactMap { $0 }.flatMap { $0 }.map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(Array(optionalNumbers.compactMap { $0 }.joined()).map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

let nonOptionalNumbers = [[1, 2, 3], [4], [5, 6, 7, 8, 9]]
print(nonOptionalNumbers.compactMap { $0 }) // [[1, 2, 3], [4], [5, 6, 7, 8, 9]]
print(nonOptionalNumbers.reduce([], +)) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nonOptionalNumbers.flatMap { $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(Array(nonOptionalNumbers.joined())) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

答案 10 :(得分:0)

Swift 5.1

public extension Array where Element: Collection {

    func flatten() -> [Element.Element] {
        return reduce([], +)
    }
}

如果您还希望使用它作为字典值:

public extension Dictionary.Values where Value : Collection {
    func flatten() -> [Value.Element]{
         return self.reduce([], +)
    }
}

答案 11 :(得分:-1)

func convert(){
    let arr = [[1,2,3],[4],[5,6,7,8,9]]
    print("Old Arr = ",arr)
    var newArr = [Int]()
    for i in arr{
        for j in i{
            newArr.append(j)
        }
    }
    print("New Arr = ",newArr)
}

enter image description here

答案 12 :(得分:-1)

矩阵是[[myDTO]]?

在Swift 5中,您可以使用此= Array(self.matrix!.joined())

答案 13 :(得分:-2)