@@ -113,4 +113,116 @@ describe("Random", () =>
113113 expect ( ( ) => Random . Choice ( [ ] ) ) . toThrow ( ValueException ) ;
114114 } ) ;
115115 } ) ;
116+
117+ describe ( "Sample" , ( ) =>
118+ {
119+ describe ( "Without weights" , ( ) =>
120+ {
121+ it ( "Should return an array with the specified number of elements from the original array" , ( ) =>
122+ {
123+ const elements = [ 1 , 2 , 3 , 4 , 5 ] ;
124+ const sample = Random . Sample ( elements , 3 ) ;
125+
126+ expect ( sample ) . toHaveLength ( 3 ) ;
127+
128+ for ( const element of sample )
129+ {
130+ expect ( elements ) . toContain ( element ) ;
131+ }
132+ } ) ;
133+
134+ it ( "Should return unique elements (no replacement)" , ( ) =>
135+ {
136+ const elements = [ 1 , 2 , 3 , 4 , 5 ] ;
137+ const sample = Random . Sample ( elements , 5 ) ;
138+
139+ const uniqueElements = new Set ( sample ) ;
140+ expect ( uniqueElements . size ) . toBe ( 5 ) ;
141+ } ) ;
142+ it ( "Should return an empty array when count is 0" , ( ) =>
143+ {
144+ const elements = [ 1 , 2 , 3 , 4 , 5 ] ;
145+ const sample = Random . Sample ( elements , 0 ) ;
146+
147+ expect ( sample ) . toHaveLength ( 0 ) ;
148+ } ) ;
149+ it ( "Should return all elements when count equals length" , ( ) =>
150+ {
151+ const elements = [ 1 , 2 , 3 , 4 , 5 ] ;
152+ const sample = Random . Sample ( elements , 5 ) ;
153+
154+ expect ( sample ) . toHaveLength ( 5 ) ;
155+ expect ( sample . sort ( ) ) . toEqual ( elements . sort ( ) ) ;
156+ } ) ;
157+
158+ it ( "Should throw `ValueException` if the array is empty" , ( ) =>
159+ {
160+ expect ( ( ) => Random . Sample ( [ ] , 1 ) ) . toThrow ( ValueException ) ;
161+ } ) ;
162+ it ( "Should throw `ValueException` if count is negative" , ( ) =>
163+ {
164+ expect ( ( ) => Random . Sample ( [ 1 , 2 , 3 ] , - 1 ) ) . toThrow ( ValueException ) ;
165+ } ) ;
166+ it ( "Should throw `ValueException` if count exceeds array length" , ( ) =>
167+ {
168+ expect ( ( ) => Random . Sample ( [ 1 , 2 , 3 ] , 5 ) ) . toThrow ( ValueException ) ;
169+ } ) ;
170+ } ) ;
171+
172+ describe ( "With weights" , ( ) =>
173+ {
174+ it ( "Should return an array with the specified number of elements from the original array" , ( ) =>
175+ {
176+ const elements = [ "a" , "b" , "c" ] ;
177+ const weights = [ 1 , 1 , 1 ] ;
178+ const sample = Random . Sample ( elements , 2 , weights ) ;
179+
180+ expect ( sample ) . toHaveLength ( 2 ) ;
181+
182+ for ( const element of sample )
183+ {
184+ expect ( elements ) . toContain ( element ) ;
185+ }
186+ } ) ;
187+
188+ it ( "Should return unique elements (no replacement)" , ( ) =>
189+ {
190+ const elements = [ "a" , "b" , "c" , "d" , "e" ] ;
191+ const weights = [ 1 , 2 , 3 , 4 , 5 ] ;
192+ const sample = Random . Sample ( elements , 5 , weights ) ;
193+
194+ const uniqueElements = new Set ( sample ) ;
195+
196+ expect ( uniqueElements . size ) . toBe ( 5 ) ;
197+ } ) ;
198+ it ( "Should favor elements with higher weights" , ( ) =>
199+ {
200+ const elements = [ "rare" , "common" ] ;
201+ const weights = [ 1 , 100 ] ;
202+
203+ let commonFirstCount = 0 ;
204+ for ( let i = 0 ; i < 1000 ; i += 1 )
205+ {
206+ const sample = Random . Sample ( elements , 1 , weights ) ;
207+
208+ if ( sample [ 0 ] === "common" ) { commonFirstCount += 1 ; }
209+ }
210+
211+ expect ( commonFirstCount ) . toBeGreaterThan ( 900 ) ;
212+ } ) ;
213+
214+ it ( "Should throw `ValueException` if weights length differs from elements length" , ( ) =>
215+ {
216+ expect ( ( ) => Random . Sample ( [ 1 , 2 , 3 ] , 2 , [ 1 , 1 ] ) ) . toThrow ( ValueException ) ;
217+ } ) ;
218+ it ( "Should throw `ValueException` if any weight is zero" , ( ) =>
219+ {
220+ expect ( ( ) => Random . Sample ( [ 1 , 2 , 3 ] , 2 , [ 1 , 0 , 1 ] ) ) . toThrow ( ValueException ) ;
221+ } ) ;
222+ it ( "Should throw `ValueException` if any weight is negative" , ( ) =>
223+ {
224+ expect ( ( ) => Random . Sample ( [ 1 , 2 , 3 ] , 2 , [ 1 , - 1 , 1 ] ) ) . toThrow ( ValueException ) ;
225+ } ) ;
226+ } ) ;
227+ } ) ;
116228} ) ;
0 commit comments