@@ -148,3 +148,150 @@ StructArrays.SkipConstructor(::Type{<:S}) = true
148
148
@test v[1 ] == S (1 )
149
149
@test v[1 ]. y isa Float64
150
150
end
151
+
152
+ const initializer = StructArrays. ArrayInitializer (t -> t <: Union{Tuple, NamedTuple, Pair} )
153
+ collect_columns (t) = StructArrays. collect_columns (t, initializer = initializer)
154
+
155
+ @testset " collectnamedtuples" begin
156
+ v = [(a = 1 , b = 2 ), (a = 1 , b = 3 )]
157
+ collect_columns (v) == StructArray ((a = Int[1 , 1 ], b = Int[2 , 3 ]))
158
+
159
+ # test inferrability with constant eltype
160
+ itr = [(a = 1 , b = 2 ), (a = 1 , b = 2 ), (a = 1 , b = 12 )]
161
+ el, st = iterate (itr)
162
+ dest = initializer (typeof (el), (3 ,))
163
+ dest[1 ] = el
164
+ @inferred StructArrays. collect_to_columns! (dest, itr, 2 , st)
165
+
166
+ v = [(a = 1 , b = 2 ), (a = 1.2 , b = 3 )]
167
+ @test collect_columns (v) == StructArray ((a = [1 , 1.2 ], b = Int[2 , 3 ]))
168
+ @test typeof (collect_columns (v)) == typeof (StructArray ((a = [1 , 1.2 ], b = Int[2 , 3 ])))
169
+
170
+ v = [(a = 1 , b = 2 ), (a = 1.2 , b = " 3" )]
171
+ @test collect_columns (v) == StructArray ((a = [1 , 1.2 ], b = Any[2 , " 3" ]))
172
+ @test typeof (collect_columns (v)) == typeof (StructArray ((a = [1 , 1.2 ], b = Any[2 , " 3" ])))
173
+
174
+ v = [(a = 1 , b = 2 ), (a = 1.2 , b = 2 ), (a = 1 , b = " 3" )]
175
+ @test collect_columns (v) == StructArray ((a = [1 , 1.2 , 1 ], b = Any[2 , 2 , " 3" ]))
176
+ @test typeof (collect_columns (v)) == typeof (StructArray ((a = [1 , 1.2 , 1 ], b = Any[2 , 2 , " 3" ])))
177
+
178
+ # length unknown
179
+ itr = Iterators. filter (isodd, 1 : 8 )
180
+ tuple_itr = ((a = i+ 1 , b = i- 1 ) for i in itr)
181
+ @test collect_columns (tuple_itr) == StructArray ((a = [2 , 4 , 6 , 8 ], b = [0 , 2 , 4 , 6 ]))
182
+ tuple_itr_real = (i == 1 ? (a = 1.2 , b = i- 1 ) : (a = i+ 1 , b = i- 1 ) for i in itr)
183
+ @test collect_columns (tuple_itr_real) == StructArray ((a = Real[1.2 , 4 , 6 , 8 ], b = [0 , 2 , 4 , 6 ]))
184
+
185
+ # empty
186
+ itr = Iterators. filter (t -> t > 10 , 1 : 8 )
187
+ tuple_itr = ((a = i+ 1 , b = i- 1 ) for i in itr)
188
+ @test collect_columns (tuple_itr) == StructArray ((a = Int[], b = Int[]))
189
+
190
+ itr = (i for i in 0 : - 1 )
191
+ tuple_itr = ((a = i+ 1 , b = i- 1 ) for i in itr)
192
+ @test collect_columns (tuple_itr) == StructArray ((a = Int[], b = Int[]))
193
+ end
194
+
195
+ @testset " collecttuples" begin
196
+ v = [(1 , 2 ), (1 , 3 )]
197
+ @test collect_columns (v) == StructArray ((Int[1 , 1 ], Int[2 , 3 ]))
198
+ @inferred collect_columns (v)
199
+
200
+ @test StructArrays. collect_columns (v) == StructArray ((Int[1 , 1 ], Int[2 , 3 ]))
201
+ @inferred StructArrays. collect_columns (v)
202
+
203
+ v = [(1 , 2 ), (1.2 , 3 )]
204
+ @test collect_columns (v) == StructArray (([1 , 1.2 ], Int[2 , 3 ]))
205
+
206
+ v = [(1 , 2 ), (1.2 , " 3" )]
207
+ @test collect_columns (v) == StructArray (([1 , 1.2 ], Any[2 , " 3" ]))
208
+ @test typeof (collect_columns (v)) == typeof (StructArray (([1 , 1.2 ], Any[2 , " 3" ])))
209
+
210
+ v = [(1 , 2 ), (1.2 , 2 ), (1 , " 3" )]
211
+ @test collect_columns (v) == StructArray (([1 , 1.2 , 1 ], Any[2 , 2 , " 3" ]))
212
+ # length unknown
213
+ itr = Iterators. filter (isodd, 1 : 8 )
214
+ tuple_itr = ((i+ 1 , i- 1 ) for i in itr)
215
+ @test collect_columns (tuple_itr) == StructArray (([2 , 4 , 6 , 8 ], [0 , 2 , 4 , 6 ]))
216
+ tuple_itr_real = (i == 1 ? (1.2 , i- 1 ) : (i+ 1 , i- 1 ) for i in itr)
217
+ @test collect_columns (tuple_itr_real) == StructArray (([1.2 , 4 , 6 , 8 ], [0 , 2 , 4 , 6 ]))
218
+ @test typeof (collect_columns (tuple_itr_real)) == typeof (StructArray (([1.2 , 4 , 6 , 8 ], [0 , 2 , 4 , 6 ])))
219
+
220
+ # empty
221
+ itr = Iterators. filter (t -> t > 10 , 1 : 8 )
222
+ tuple_itr = ((i+ 1 , i- 1 ) for i in itr)
223
+ @test collect_columns (tuple_itr) == StructArray ((Int[], Int[]))
224
+
225
+ itr = (i for i in 0 : - 1 )
226
+ tuple_itr = ((i+ 1 , i- 1 ) for i in itr)
227
+ @test collect_columns (tuple_itr) == StructArray ((Int[], Int[]))
228
+ end
229
+
230
+ @testset " collectscalars" begin
231
+ v = (i for i in 1 : 3 )
232
+ @test collect_columns (v) == [1 ,2 ,3 ]
233
+ @inferred collect_columns (v)
234
+
235
+ v = (i == 1 ? 1.2 : i for i in 1 : 3 )
236
+ @test collect_columns (v) == collect (v)
237
+
238
+ itr = Iterators. filter (isodd, 1 : 100 )
239
+ @test collect_columns (itr) == collect (itr)
240
+ real_itr = (i == 1 ? 1.5 : i for i in itr)
241
+ @test collect_columns (real_itr) == collect (real_itr)
242
+ @test eltype (collect_columns (real_itr)) == Float64
243
+
244
+ # empty
245
+ itr = Iterators. filter (t -> t > 10 , 1 : 8 )
246
+ tuple_itr = (exp (i) for i in itr)
247
+ @test collect_columns (tuple_itr) == Float64[]
248
+
249
+ itr = (i for i in 0 : - 1 )
250
+ tuple_itr = (exp (i) for i in itr)
251
+ @test collect_columns (tuple_itr) == Float64[]
252
+
253
+ t = collect_columns ((a = i,) for i in (1 , missing , 3 ))
254
+ @test StructArrays. columns (t)[1 ] isa Array{Union{Int, Missing}}
255
+ @test isequal (StructArrays. columns (t)[1 ], [1 , missing , 3 ])
256
+ end
257
+
258
+ @testset " collectpairs" begin
259
+ v = (i=> i+ 1 for i in 1 : 3 )
260
+ @test collect_columns (v) == StructArray {Pair{Int, Int}} ([1 ,2 ,3 ], [2 ,3 ,4 ])
261
+ @test eltype (collect_columns (v)) == Pair{Int, Int}
262
+
263
+ v = (i == 1 ? (1.2 => i+ 1 ) : (i => i+ 1 ) for i in 1 : 3 )
264
+ @test collect_columns (v) == StructArray {Pair{Float64, Int}} ([1.2 ,2 ,3 ], [2 ,3 ,4 ])
265
+ @test eltype (collect_columns (v)) == Pair{Float64, Int}
266
+
267
+ v = ((a= i,) => (b= " a$i " ,) for i in 1 : 3 )
268
+ @test collect_columns (v) == StructArray{Pair{NamedTuple{(:a ,),Tuple{Int64}},NamedTuple{(:b ,),Tuple{String}}}}(StructArray ((a = [1 ,2 ,3 ],)), StructArray ((b = [" a1" ," a2" ," a3" ],)))
269
+ @test eltype (collect_columns (v)) == Pair{NamedTuple{(:a ,), Tuple{Int64}}, NamedTuple{(:b ,), Tuple{String}}}
270
+
271
+ v = (i == 1 ? (a= " 1" ,) => (b= " a$i " ,) : (a= i,) => (b= " a$i " ,) for i in 1 : 3 )
272
+ @test collect_columns (v) == StructArray{Pair{NamedTuple{(:a ,),Tuple{Any}},NamedTuple{(:b ,),Tuple{String}}}}(StructArray ((a = [" 1" ,2 ,3 ],)), StructArray ((b = [" a1" ," a2" ," a3" ],)))
273
+ @test eltype (collect_columns (v)) == Pair{NamedTuple{(:a ,), Tuple{Any}}, NamedTuple{(:b ,), Tuple{String}}}
274
+
275
+ # empty
276
+ v = ((a= i,) => (b= " a$i " ,) for i in 0 : - 1 )
277
+ @test collect_columns (v) == StructArray{Pair{NamedTuple{(:a ,),Tuple{Int64}},NamedTuple{(:b ,),Tuple{String}}}}(StructArray ((a = Int[],)), StructArray ((b = String[],)))
278
+ @test eltype (collect_columns (v)) == Pair{NamedTuple{(:a ,), Tuple{Int}}, NamedTuple{(:b ,), Tuple{String}}}
279
+
280
+ v = Iterators. filter (t -> t. first. a == 4 , ((a= i,) => (b= " a$i " ,) for i in 1 : 3 ))
281
+ @test collect_columns (v) == StructArray{Pair{NamedTuple{(:a ,),Tuple{Int64}},NamedTuple{(:b ,),Tuple{String}}}}(StructArray ((a = Int[],)), StructArray ((b = String[],)))
282
+ @test eltype (collect_columns (v)) == Pair{NamedTuple{(:a ,), Tuple{Int}}, NamedTuple{(:b ,), Tuple{String}}}
283
+
284
+ t = collect_columns ((b = 1 ,) => (a = i,) for i in (2 , missing , 3 ))
285
+ s = StructArray{Pair{NamedTuple{(:b ,),Tuple{Int64}},NamedTuple{(:a ,),Tuple{Union{Missing, Int64}}}}}(StructArray (b = [1 ,1 ,1 ]), StructArray (a = [2 , missing , 3 ]))
286
+ @test s[1 ] == t[1 ]
287
+ @test ismissing (t[2 ]. second. a)
288
+ @test s[3 ] == t[3 ]
289
+ end
290
+
291
+ @testset " collect2D" begin
292
+ s = (l for l in [(a= i, b= j) for i in 1 : 3 , j in 1 : 4 ])
293
+ v = StructArrays. collect_columns (s)
294
+ @test size (v) == (3 , 4 )
295
+ @test v. a == [i for i in 1 : 3 , j in 1 : 4 ]
296
+ @test v. b == [j for i in 1 : 3 , j in 1 : 4 ]
297
+ end
0 commit comments