+1
-1
| { | ||
| "name": "grid-sort", | ||
| "version": "2.1.0", | ||
| "version": "2.1.1", | ||
| "description": "Sort objects in a two dimensional array to compose grids based on a condition", | ||
@@ -5,0 +5,0 @@ "main": "./lib/index.js", |
Sorry, the diff of this file is not supported yet
| name: CI | ||
| on: [push, pull_request] | ||
| jobs: | ||
| test: | ||
| name: Test | ||
| runs-on: ubuntu-20.04 | ||
| timeout-minutes: 3 | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - uses: actions/setup-node@v1 | ||
| with: | ||
| node-version: 14 | ||
| - name: Dependencies | ||
| run: yarn install --frozen-lockfile | ||
| - name: Test with coverage | ||
| run: | | ||
| yarn check-coverage | ||
| yarn report-coverage | ||
| - uses: codecov/codecov-action@v2 | ||
| with: | ||
| token: ${{ secrets.CODECOV_TOKEN }} | ||
| files: ./coverage.lcov | ||
| name: Codecov | ||
| {"version":3,"file":"gridSort.js","sourceRoot":"","sources":["../src/gridSort.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,GAAG,CAAmB,MAAS,EAAE,EAAE,CAC7C,MAAM,CAAC,IAAI,CAAC,MAAM,CAA4B,CAAC;AAEjD,MAAM,aAAa,GAAG,CACpB,OAAmB,EACnB,GAAqB,EACrB,EAAE,WAAC,OAAA,CAAA,MAAA,OAAO,CAAC,GAAG,CAAC,0CAAE,MAAM,KAAI,CAAC,GAAG,CAAC,CAAA,EAAA,CAAC;AAEnC,MAAM,WAAW,GAAG,CAClB,GAAQ,EACR,QAAqD,EACrD,EAAE,CACF,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,GAAG,GAAG,KAAK,CAAC;KACpB;IAED,OAAO,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC,EAAE,CAAC,CAAC,CAAC;AAER,MAAM,UAAU,aAAa,CAAI,OAAmB;IAClD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAI,OAAmB,EAAE,OAAe,EAAE,QAAqD;IAC/H,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;SAC1B,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACtB,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACxC,IAAI,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBACzC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;aACxB;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC;QAE5C,OAAO,GAAG,GAAG,cAAc,CAAC;IAC9B,CAAC,EAAE,CAAC,CAAC,CAAC;AACV,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,IAAS,EACT,IAAS,EACT,QAAqD;IAErD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACjC,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAM,CAAC;QAE7B,IAAI,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YACtE,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;SAC5C;QAED,OAAO,KAAK,KAAK,KAAK,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAU,EACV,QAAqD;IAErD,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACxB,IAAI,GAAW,CAAC;QAEhB,IAAI,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;YACxC,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;SACtB;aAAM;YACL,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;SACpB;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAE1B,IAAI,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACjC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SAClB;aAAM;YACL,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;SACtB;KACF;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,OAAmB,EAAE,MAAc;IACpE,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;QAC5B,IACE,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC;YAC3B,GAAG,GAAG,iBAAiB;YACvB,GAAG,IAAI,MAAM,EACb;YACA,iBAAiB,GAAG,GAAG,CAAC;SACzB;KACF;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAA4B,EAC9D,OAAO,EACP,OAAO,EACP,QAAQ,GAKT;;IACC,MAAM,IAAI,GAAU,EAAE,CAAC;IAEvB,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9B,IAAI,SAAiB,CAAC;IAEtB,OAAO,CAAC,SAAS,GAAG,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE;QACvE,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,IAAI,GAAW,CAAC;QAEhB,OACE,CAAC,GAAG,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;YACtE,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,OAAO;YACpC,SAAS,IAAI,CAAC,EACd;YACA,MAAM,IAAI,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,0CAAE,KAAK,EAAE,CAAC;YACnC,IAAI,IAAI,EAAE;gBACR,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAChB;SACF;QAED,wDAAwD;QACxD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC1C,IAAI,WAAW,IAAI,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE;YAC3D,GAAG,CAAC,OAAO,EAAE,CAAC;SACf;QAED,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KAChB;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,QAAQ,CAA4B,EAClD,KAAK,EACL,OAAO,GAAG,CAAC,EACX,QAAQ,GAKT;IACC,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnD,OAAO,oBAAoB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9D,CAAC"} |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"} |
-155
| export type Bucket<T> = T[]; | ||
| export type Buckets<T> = { [key: number]: Bucket<T> }; | ||
| export type Accessor<T extends object> = (item: T) => number; | ||
| const keysOf = <T extends object>(object: T) => | ||
| Object.keys(object) as (keyof typeof object)[]; | ||
| const itemsInBucket = <T extends unknown>( | ||
| buckets: Buckets<T>, | ||
| key: keyof Buckets<T> | ||
| ) => buckets[key]?.length || 0 > 0; | ||
| const rowQuantity = <T extends object | number>( | ||
| row: T[], | ||
| accessor?: T extends object ? Accessor<T> : undefined | ||
| ) => | ||
| row.reduce((acc, item) => { | ||
| if (accessor && typeof item === "object") { | ||
| const value = accessor(item); | ||
| return acc + value; | ||
| } | ||
| return acc + Number(item); | ||
| }, 0); | ||
| export function getSortedKeys<T>(buckets: Buckets<T>) { | ||
| return keysOf(buckets).sort((a, z) => z - a); | ||
| } | ||
| export function calculateItemsLeft<T>(buckets: Buckets<T>, columns: number, accessor?: T extends object ? Accessor<T> : undefined) { | ||
| return Object.values(buckets) | ||
| .reduce((acc, bucket) => { | ||
| const bucketQuantity = bucket.map(value => { | ||
| if (accessor && typeof value === 'object') { | ||
| return accessor(value); | ||
| } | ||
| return value; | ||
| }).filter(value => value <= columns).length; | ||
| return acc + bucketQuantity; | ||
| }, 0); | ||
| } | ||
| export function rowsAreEqual<T extends object | number>( | ||
| rowA: T[], | ||
| rowB: T[], | ||
| accessor?: T extends object ? Accessor<T> : undefined | ||
| ) { | ||
| return rowA.every((value, index) => { | ||
| let itemA = value; | ||
| let itemB = rowB[index] as T; | ||
| if (accessor && typeof itemA === "object" && typeof itemB === "object") { | ||
| return accessor(itemA) === accessor(itemB); | ||
| } | ||
| return itemA === itemB; | ||
| }); | ||
| } | ||
| export function groupItemsByValue<T extends object | number>( | ||
| items: T[], | ||
| accessor?: T extends object ? Accessor<T> : undefined | ||
| ) { | ||
| const groups: Buckets<T> = {}; | ||
| for (const item of items) { | ||
| let key: number; | ||
| if (accessor && typeof item === "object") { | ||
| key = accessor(item); | ||
| } else { | ||
| key = Number(item); | ||
| } | ||
| const group = groups[key]; | ||
| if (group && Array.isArray(group)) { | ||
| group.push(item); | ||
| } else { | ||
| groups[key] = [item]; | ||
| } | ||
| } | ||
| return groups; | ||
| } | ||
| export function getFillableItem<T>(buckets: Buckets<T>, maxKey: number) { | ||
| let currentBiggestKey = 0; | ||
| const sortedKeys = getSortedKeys(buckets); | ||
| for (const key of sortedKeys) { | ||
| if ( | ||
| itemsInBucket(buckets, key) && | ||
| key > currentBiggestKey && | ||
| key <= maxKey | ||
| ) { | ||
| currentBiggestKey = key; | ||
| } | ||
| } | ||
| return currentBiggestKey; | ||
| } | ||
| export function buildGridFromBuckets<T extends object | number>({ | ||
| buckets, | ||
| columns, | ||
| accessor, | ||
| }: { | ||
| buckets: Buckets<T>; | ||
| columns: number; | ||
| accessor?: T extends object ? Accessor<T> : undefined; | ||
| }) { | ||
| const grid: T[][] = []; | ||
| if (columns <= 0) return grid; | ||
| let itemsLeft: number; | ||
| while ((itemsLeft = calculateItemsLeft(buckets, columns, accessor)) > 0) { | ||
| const row: T[] = []; | ||
| let key: number; | ||
| while ( | ||
| (key = getFillableItem(buckets, columns - rowQuantity(row, accessor))) && | ||
| rowQuantity(row, accessor) < columns && | ||
| itemsLeft >= 1 | ||
| ) { | ||
| const item = buckets[key]?.shift(); | ||
| if (item) { | ||
| row.push(item); | ||
| } | ||
| } | ||
| // randomize current row if previous row has same layout | ||
| const previousRow = grid[grid.length - 1]; | ||
| if (previousRow && rowsAreEqual(row, previousRow, accessor)) { | ||
| row.reverse(); | ||
| } | ||
| grid.push(row); | ||
| } | ||
| return grid; | ||
| } | ||
| export function gridSort<T extends object | number>({ | ||
| items, | ||
| columns = 4, | ||
| accessor, | ||
| }: { | ||
| items: T[]; | ||
| columns?: number; | ||
| accessor?: T extends object ? Accessor<T> : never; | ||
| }) { | ||
| const buckets = groupItemsByValue(items, accessor); | ||
| return buildGridFromBuckets({ buckets, columns, accessor }); | ||
| } |
| export { gridSort } from "./gridSort.js"; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| import { test, suite } from "uvu"; | ||
| import * as assert from "uvu/assert"; | ||
| import { | ||
| buildGridFromBuckets, | ||
| getFillableItem, | ||
| getSortedKeys, | ||
| groupItemsByValue, | ||
| rowsAreEqual, | ||
| } from "../src/gridSort.js"; | ||
| test("sorts object keys numerically in descending order", () => { | ||
| const buckets = { 1: [1, 1, 1], 2: [2, 2], 3: [3, 3] }; | ||
| assert.equal(getSortedKeys(buckets), [3, 2, 1].map(String)); | ||
| }); | ||
| test("gets best candidate for filling a column", () => { | ||
| const bucketsA = { 1: [1, 1, 1], 2: [2, 2], 3: [3, 3] }; | ||
| assert.equal(getFillableItem(bucketsA, 4), "3"); | ||
| const bucketsB = { 1: [1, 1, 1], 2: [2, 2], 3: [3, 3] }; | ||
| assert.equal(getFillableItem(bucketsB, 1), "1"); | ||
| const bucketsC = { 1: [1, 1, 1], 2: [2, 2], 3: [3, 3] }; | ||
| assert.equal(getFillableItem(bucketsC, 2), "2"); | ||
| const bucketsD = { 1: [1, 1, 1], 2: [2, 2], 3: [] }; | ||
| assert.equal(getFillableItem(bucketsD, 4), "2"); | ||
| const bucketsE = { 1: [1, 1, 1], 2: [], 3: [] }; | ||
| assert.equal(getFillableItem(bucketsE, 4), "1"); | ||
| const bucketsF = { 1: [1, 1, 1], 2: [2, 2], 3: [3, 3] }; | ||
| assert.equal(getFillableItem(bucketsF, 2), "2"); | ||
| const bucketsG = { 1: [1, 1, 1], 2: [2, 2], 3: [3, 3] }; | ||
| assert.equal(getFillableItem(bucketsG, 1), "1"); | ||
| }); | ||
| test("rows equality", () => { | ||
| const [rowA, rowB] = [ | ||
| [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| ], | ||
| [ | ||
| { id: "8", ratio: 3 }, | ||
| { id: "5", ratio: 1 }, | ||
| ], | ||
| ]; | ||
| const accessor = (item: typeof rowA[number]) => item.ratio; | ||
| assert.ok(rowsAreEqual(rowA, rowB, accessor)); | ||
| assert.not.ok(rowsAreEqual(rowA, rowB.reverse(), accessor)); | ||
| }); | ||
| test("it sorts bucket of numbers", () => { | ||
| const buckets = groupItemsByValue([1, 1, 1, 1, 1, 2, 2, 3, 3]); | ||
| const sorted = buildGridFromBuckets({ | ||
| buckets, | ||
| columns: 4, | ||
| accessor: undefined, | ||
| }); | ||
| const expected = [ | ||
| [3, 1], | ||
| [1, 3], | ||
| [2, 2], | ||
| [1, 1, 1], | ||
| ]; | ||
| assert.equal(sorted, expected); | ||
| }); | ||
| test("it builds buckets from array of items", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const itemsByValue = groupItemsByValue(items, (item) => item.ratio); | ||
| assert.equal(itemsByValue, { | ||
| 1: [ | ||
| { id: "2", ratio: 1 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| ], | ||
| 2: [ | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| ], | ||
| 3: [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "8", ratio: 3 }, | ||
| ], | ||
| }); | ||
| }); | ||
| test("it sorts bucket of objects", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const accessor = (item: typeof items[number]) => item.ratio; | ||
| const itemsByValue = groupItemsByValue(items, accessor); | ||
| const sorted = buildGridFromBuckets({ | ||
| buckets: itemsByValue, | ||
| columns: 4, | ||
| accessor, | ||
| }); | ||
| const expected = [ | ||
| [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| ], | ||
| [ | ||
| { id: "5", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ], | ||
| [ | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| ], | ||
| [{ id: "7", ratio: 1 }], | ||
| ]; | ||
| assert.equal(sorted, expected); | ||
| }); | ||
| test.run(); | ||
| const ColumnSuite = suite('Columns Suite'); | ||
| ColumnSuite("it sorts bucket of objects with more columns", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const accessor = (item: typeof items[number]) => item.ratio; | ||
| const itemsByValue = groupItemsByValue(items, accessor); | ||
| const sorted = buildGridFromBuckets({ | ||
| buckets: itemsByValue, | ||
| columns: 5, | ||
| accessor, | ||
| }); | ||
| const expected = [ | ||
| [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "3", ratio: 2 }, | ||
| ], | ||
| [ | ||
| { id: "4", ratio: 2 }, | ||
| { id: "8", ratio: 3 }, | ||
| ], | ||
| [ | ||
| { id: "2", ratio: 1 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| ], | ||
| ]; | ||
| assert.equal(sorted, expected); | ||
| }); | ||
| ColumnSuite("it sorts bucket of objects with less columns than items", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const accessor = (item: typeof items[number]) => item.ratio; | ||
| const itemsByValue = groupItemsByValue(items, accessor); | ||
| const sorted = buildGridFromBuckets({ | ||
| buckets: itemsByValue, | ||
| columns: 3, | ||
| accessor, | ||
| }); | ||
| const expected = [ | ||
| [ | ||
| { id: "1", ratio: 3 }, | ||
| ], | ||
| [ | ||
| { id: "8", ratio: 3 }, | ||
| ], | ||
| [ | ||
| { id: "3", ratio: 2 }, | ||
| { id: "2", ratio: 1 }, | ||
| ], | ||
| [ | ||
| { id: "5", ratio: 1 }, | ||
| { id: "4", ratio: 2 }, | ||
| ], | ||
| [ | ||
| { id: "7", ratio: 1 }, | ||
| ] | ||
| ]; | ||
| assert.equal(sorted, expected); | ||
| }); | ||
| ColumnSuite("it sorts bucket of objects with less columns than biggest object", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const accessor = (item: typeof items[number]) => item.ratio; | ||
| const itemsByValue = groupItemsByValue(items, accessor); | ||
| const sorted = buildGridFromBuckets({ | ||
| buckets: itemsByValue, | ||
| columns: 2, | ||
| accessor, | ||
| }); | ||
| const expected = [ | ||
| [ | ||
| { id: "3", ratio: 2 }, | ||
| ], | ||
| [ | ||
| { id: "4", ratio: 2 }, | ||
| ], | ||
| [ | ||
| { id: "2", ratio: 1 }, | ||
| { id: "5", ratio: 1 }, | ||
| ], | ||
| [ | ||
| { id: "7", ratio: 1 }, | ||
| ] | ||
| ]; | ||
| assert.equal(sorted, expected); | ||
| }); | ||
| ColumnSuite("it sorts bucket of objects with a single column", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const accessor = (item: typeof items[number]) => item.ratio; | ||
| const itemsByValue = groupItemsByValue(items, accessor); | ||
| const sorted = buildGridFromBuckets({ | ||
| buckets: itemsByValue, | ||
| columns: 1, | ||
| accessor, | ||
| }); | ||
| const expected = [ | ||
| [ | ||
| { id: "2", ratio: 1 }, | ||
| ], | ||
| [ | ||
| { id: "5", ratio: 1 }, | ||
| ], | ||
| [ | ||
| { id: "7", ratio: 1 }, | ||
| ] | ||
| ]; | ||
| assert.equal(sorted, expected); | ||
| }); | ||
| ColumnSuite("it sorts bucket of objects with no columns", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const accessor = (item: typeof items[number]) => item.ratio; | ||
| const itemsByValue = groupItemsByValue(items, accessor); | ||
| const sorted = buildGridFromBuckets({ | ||
| buckets: itemsByValue, | ||
| columns: 0, | ||
| accessor, | ||
| }); | ||
| assert.equal(sorted, []); | ||
| }); | ||
| ColumnSuite.run(); |
| import { test } from "uvu"; | ||
| import * as assert from "uvu/assert"; | ||
| import { gridSort } from "../src/index.js"; | ||
| test("it sorts an array of items into a grid", () => { | ||
| const items = [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "2", ratio: 1 }, | ||
| { id: "3", ratio: 2 }, | ||
| { id: "4", ratio: 2 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| { id: "8", ratio: 3 }, | ||
| ]; | ||
| const accessor = (item: typeof items[number]) => item.ratio; | ||
| const sorted = gridSort({ | ||
| items, | ||
| columns: 5, | ||
| accessor, | ||
| }); | ||
| const expected = [ | ||
| [ | ||
| { id: "1", ratio: 3 }, | ||
| { id: "3", ratio: 2 }, | ||
| ], | ||
| [ | ||
| { id: "4", ratio: 2 }, | ||
| { id: "8", ratio: 3 }, | ||
| ], | ||
| [ | ||
| { id: "2", ratio: 1 }, | ||
| { id: "5", ratio: 1 }, | ||
| { id: "7", ratio: 1 }, | ||
| ], | ||
| ]; | ||
| assert.equal(sorted, expected); | ||
| }); | ||
| test.run(); |
| { | ||
| "compilerOptions": { | ||
| "declaration": true, | ||
| "esModuleInterop": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "lib": ["ESNext"], | ||
| "module": "ES2020", | ||
| "moduleResolution": "node", | ||
| "noFallthroughCasesInSwitch": true, | ||
| "noImplicitAny": true, | ||
| "noImplicitOverride": true, | ||
| "noImplicitReturns": true, | ||
| "noImplicitThis": true, | ||
| "noPropertyAccessFromIndexSignature": true, | ||
| "noUncheckedIndexedAccess": true, | ||
| "noUnusedLocals": true, | ||
| "noUnusedParameters": true, | ||
| "outDir": "./lib", | ||
| "strict": true, | ||
| "strictBindCallApply": true, | ||
| "strictFunctionTypes": true, | ||
| "strictNullChecks": true, | ||
| "strictPropertyInitialization": true, | ||
| "skipLibCheck": true, | ||
| "target": "ES2015", | ||
| "sourceMap": true | ||
| }, | ||
| "include": ["src"] | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
10660
-95.19%6
-66.67%118
-80.1%