Apakah ada rekan di Swift flatten
di Scala, Xtend, Groovy, Ruby dan co?
var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatten() // shall deliver [1,2,3,4,5,6,7,8,9]
Tentu saja saya bisa menggunakan pengurangan untuk itu tapi itu agak menyebalkan
var flattened = aofa.reduce(Int[]()){
a,i in var b : Int[] = a
b.extend(i)
return b
}
Jawaban:
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())
sumber
flatMap
tersedia pada Swift 1.2.joined
(secara resmi dikenal sebagaiflatten
) denganflatMap
? Apakah saatflatMap
bergabung, ia juga dapat memetakan / mengubah sesuatu. tapi di sini, dalam contoh kita benar-benar tidak perlu yaitu kita kembali$0
flatMap
akan baik meratakan array 2D ke dalam array 1D atau menghapusnil
nilai-nilai, tidak keduanya. Ini menentukan apa yang harus dilakukan berdasarkan apakah larik tingkat pertamaElement
adalah larik atau opsional — jadi jika Anda meneruskannya ke larik 2D opsional (misalnya[[Int?]]
), ia akan memilih untuk meratakannya ke 1D (misalnya[Int?]
) . Untuk meratakan ke 1-D dan menghapus nol tingkat 2, Anda harus melakukannyaarray.flatMap { $0 }.flatMap { $0 }
. Dengan kata lain, perataan dimensi ekuivArray(array.joined())
dan “perataan” penghilangan nihil sama denganarray.filter{ $0 != nil }.map{ $0! }
.flatMap
masih sesuai untuk penggunaan yang dijelaskan dalam pertanyaan (meratakan array 2D ke 1D).compactMap
secara eksplisit untuk menghapusnil
item dari urutan, seperti yangflatMap
pernah dilakukan oleh varian .[[Any]]
, aflatMap
cukup mengubahnya menjadi tipe[Any]
([1, 2, 3, 4, [5, 6], 7, 8, 9]). Dan jika kita akan berlakuflatMap
lagi, kami akan bertindak pada `Setiap? type, dimana kompilator tidak tahu lagi apakah itu nilai sederhana atau array itu sendiri.Dalam Swift perpustakaan standar ada
joined
fungsi yang diimplementasikan untuk semua jenis sesuai denganSequence
protokol (atauflatten
padaSequenceType
sebelum Swift 3), yang meliputiArray
:let numbers = [[1,2,3],[4],[5,6,7,8,9]] let flattened = Array(numbers.joined())
Dalam kasus tertentu, penggunaan dari
joined()
dapat bermanfaat karena mengembalikan koleksi yang lazy daripada array baru, tetapi selalu dapat diubah menjadi array saat diteruskan keArray()
penginisialisasi seperti pada contoh di atas.sumber
FlattenBidirectionalCollection<Array<Array<Int>>>(_base: [[1, 2, 3], [4], [5, 6, 7, 8, 9]]))
. Poin Anda valid meskipun Anda dapat mengaksesnya seperti array datar, jadiCustomStringConvertable
implementasinya tampaknya menyesatkan. Cuplikan kode Anda pernah dan masih melewatkan pengujian.flatten()
telah diubah namanya menjadijoined()
Cepat 4.x / 5.x
Hanya untuk menambah sedikit kerumitan pada array, jika ada array yang berisi array, maka
flatMap
sebenarnya akan gagal.Misalkan array tersebut
var array:[Any] = [1,2,[[3,4],[5,6,[7]]],8]
Apa
flatMap
ataucompactMap
pengembaliannya adalah:array.compactMap({$0}) //Output [1, 2, [[3, 4], [5, 6, [7]]], 8]
Untuk mengatasi masalah ini, kita dapat menggunakan logika loop + rekursi sederhana kita
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 }
Jadi panggil fungsi ini dengan array yang diberikan
Hasilnya adalah:
[1, 2, 3, 4, 5, 6, 7, 8]
Fungsi ini akan membantu meratakan semua jenis larik, dengan mempertimbangkan kasus di
Int
siniOutput Taman Bermain:
sumber
Cepat 4.x
Penggunaan
flatMap
ini tidak usang dan dibuat untuk ini. https://developer.apple.com/documentation/swift/sequence/2905332-flatmapvar aofa = [[1,2,3],[4],[5,6,7,8,9]] aofa.flatMap { $0 } //[1,2,3,4,5,6,7,8,9]
sumber
Edit: Gunakan
joined()
sebagai gantinya:https://developer.apple.com/documentation/swift/sequence/2431985-joined
Balasan asli:
let numbers = [[1, 2, 3], [4, 5, 6]] let flattenNumbers = numbers.reduce([], combine: +)
sumber
Swift 4.2.0
Saya menulis ekstensi array sederhana di bawah ini. Anda dapat menggunakan untuk meratakan larik yang berisi larik atau elemen lain. tidak seperti metode 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) } }
pemakaian:
let numbers: [Any] = [1, [2, "3"], 4, ["5", 6, 7], "8", [9, 10]] numbers.flatten()
sumber
Modifikasi jawaban @ RahmiBozdag, 1. Metode dalam ekstensi publik bersifat publik. 2. Metode ekstra dihapus, karena indeks awal akan selalu nol. 3. Saya tidak menemukan cara untuk meletakkan compactMap di dalam nil dan opsional karena di dalam metode T selalu [Ada?], Saran apa pun akan diterima.
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]
sumber
Apple Swift versi 5.1.2 (swiftlang-1100.0.278 clang-1100.0.33.9)
Target: x86_64-apple-darwin19.2.0
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]
sumber
Implementasi lain yang lebih umum dari
reduce
,let numbers = [[1,2,3],[4],[5,6,7,8,9]] let reduced = reduce(numbers,[],+)
Ini menyelesaikan hal yang sama tetapi mungkin memberi lebih banyak wawasan tentang apa yang sedang terjadi
reduce
.Dari dokumen Apple,
func reduce<S : SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U) -> U
Deskripsi
Kembalikan hasil penggabungan panggilan berulang dengan nilai akumulasi yang diinisialisasi ke awal dan setiap elemen urutan , secara bergantian.
sumber
Use of unresolved identifier 'reduce'
Anda dapat meratakan array bersarang menggunakan metode berikut:
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]
sumber
Swift 5.1.0
public extension Array where Element: Collection { func flatten() -> [Element.Element] { return reduce([], +) } }
Jika Anda juga menginginkannya untuk nilai Kamus:
public extension Dictionary.Values where Value : Collection { func flatten() -> [Value.Element]{ return self.reduce([], +) } }
sumber
flatten()
diubah namanya menjadijoined()
di Swift 3 per SE-0133:https://github.com/apple/swift-evolution/blob/master/proposals/0133-rename-flatten-to-joined.md
sumber
matriks adalah [[myDTO]]?
Di swift 5 Anda bisa menggunakan this = Array (self.matrix! .Joined ())
sumber
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) }
sumber