( valueExtractor: (value: T) => number = (v) => v as unknown as number, )
| 327 | * @param valueExtractor Function to extract a value from each data entry |
| 328 | */ |
| 329 | export function mode<T>( |
| 330 | valueExtractor: (value: T) => number = (v) => v as unknown as number, |
| 331 | ): AggregateFunction<T, number, Map<number, number>> { |
| 332 | return { |
| 333 | preMap: (data: T) => { |
| 334 | const value = valueExtractor(data) |
| 335 | const frequencyMap = new Map<number, number>() |
| 336 | frequencyMap.set(value, 1) |
| 337 | return frequencyMap |
| 338 | }, |
| 339 | reduce: (values: Array<[Map<number, number>, number]>) => { |
| 340 | // Combine all frequency maps |
| 341 | const combinedMap = new Map<number, number>() |
| 342 | |
| 343 | for (const [frequencyMap, multiplicity] of values) { |
| 344 | for (const [value, frequencyCount] of frequencyMap.entries()) { |
| 345 | const currentCount = combinedMap.get(value) || 0 |
| 346 | combinedMap.set(value, currentCount + frequencyCount * multiplicity) |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | return combinedMap |
| 351 | }, |
| 352 | postMap: (result: Map<number, number>) => { |
| 353 | if (result.size === 0) return 0 |
| 354 | |
| 355 | let modeValue = 0 |
| 356 | let maxFrequency = 0 |
| 357 | |
| 358 | for (const [value, frequency] of result.entries()) { |
| 359 | if (frequency > maxFrequency) { |
| 360 | maxFrequency = frequency |
| 361 | modeValue = value |
| 362 | } |
| 363 | } |
| 364 | |
| 365 | return modeValue |
| 366 | }, |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | export const groupByOperators = { |
| 371 | sum, |
no test coverage detected