diff --git a/README.md b/README.md index 5d0fba8..c634335 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ This library compares two arrays or objects and returns a full diff of their dif ![NPM Downloads](https://img.shields.io/npm/dy/%40donedeal0%2Fsuperdiff?logo=npm) ![GitHub Tag](https://img.shields.io/github/v/tag/DoneDeal0/superdiff?label=latest%20release) - ## WHY YOU SHOULD USE THIS LIBRARY All other existing solutions return a strange diff format that often requires additional parsing. They are also limited to object comparison. 👎 @@ -19,7 +18,6 @@ All other existing solutions return a strange diff format that often requires ad I am grateful to the generous donors of **Superdiff**! -
AlexisAnzieu @@ -235,11 +233,13 @@ You can add a third `options` parameter to `getListDiff`. { showOnly?: ("added" | "deleted" | "moved" | "updated" | "equal")[], // [] by default referenceProperty?: string; // "" by default + ignoreArrayOrder?: boolean // false by default, } ``` - `showOnly` gives you the option to return only the values whose status you are interested in (e.g. `["added", "equal"]`). - `referenceProperty` will consider an object to be updated instead of added or deleted if one of its properties remains stable, such as its `id`. This option has no effect on other datatypes. +- `ignoreArrayOrder`: if set to `true`, `["hello", "world"]` and `["world", "hello"]` will be treated as `equal`, because the two arrays have the same value, just not in the same order. ### isEqual() diff --git a/package.json b/package.json index f99ba16..1bcc421 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "scripts": { "build": "tsup --dts --format esm,cjs", "publish": "npm publish --access=public", - "test": "jest" + "test": "jest", + "tsc": "tsc --noEmit" }, "devDependencies": { "@babel/preset-env": "^7.23.8", diff --git a/src/list-diff.ts b/src/list-diff.ts index ffaf55e..52e21f6 100644 --- a/src/list-diff.ts +++ b/src/list-diff.ts @@ -1,10 +1,4 @@ -import { - LIST_STATUS, - ListData, - ListDiff, - ListDiffStatus, - ListOptions, -} from "./model"; +import { LIST_STATUS, ListDiff, ListDiffStatus, ListOptions } from "./model"; import { isEqual, isObject } from "./utils"; function getLeanDiff( @@ -72,6 +66,7 @@ export const getListDiff = ( showOnly: [], referenceProperty: undefined, considerMoveAsUpdate: false, + ignoreArrayOrder: false, } ): ListDiff => { if (!prevList && !nextList) { @@ -110,7 +105,7 @@ export const getListDiff = ( prevIndexMatches.push(prevIndex); } const indexDiff = prevIndex === -1 ? null : i - prevIndex; - if (indexDiff === 0) { + if (indexDiff === 0 || options.ignoreArrayOrder) { let nextStatus = LIST_STATUS.EQUAL; if (isReferencedObject(nextValue, options.referenceProperty)) { if (!isEqual(prevList[prevIndex], nextValue)) { diff --git a/src/model.ts b/src/model.ts index ea17db8..81c75d3 100644 --- a/src/model.ts +++ b/src/model.ts @@ -55,6 +55,7 @@ export type ListOptions = { showOnly?: Array; referenceProperty?: string; considerMoveAsUpdate?: boolean; + ignoreArrayOrder?: boolean; }; export type ListDiff = { diff --git a/test/list-diff.test.ts b/test/list-diff.test.ts index e52d410..7c38a8f 100644 --- a/test/list-diff.test.ts +++ b/test/list-diff.test.ts @@ -697,4 +697,95 @@ describe("getListDiff", () => { ], }); }); + it("consider moved values as equal if they have not changed and ignoreArrayOrder option is true", () => { + expect( + getListDiff( + [ + { id: 3, name: "nina", hobbies: ["swiming"] }, + { id: 1, name: "joe", hobbies: ["golf", "fishing"] }, + { id: 2, name: "jack", hobbies: ["coding"] }, + ], + [ + { id: 1, name: "joe", hobbies: ["golf", "fishing"] }, + { id: 2, name: "jack", hobbies: ["coding"] }, + { id: 3, name: "nina", hobbies: ["swiming"] }, + ], + { + ignoreArrayOrder: true, + } + ) + ).toStrictEqual({ + type: "list", + status: "equal", + diff: [ + { + value: { id: 1, name: "joe", hobbies: ["golf", "fishing"] }, + prevIndex: 1, + newIndex: 0, + indexDiff: -1, + status: "equal", + }, + { + value: { id: 2, name: "jack", hobbies: ["coding"] }, + prevIndex: 2, + newIndex: 1, + indexDiff: -1, + status: "equal", + }, + { + value: { id: 3, name: "nina", hobbies: ["swiming"] }, + prevIndex: 0, + newIndex: 2, + indexDiff: 2, + status: "equal", + }, + ], + }); + }); + it("consider moved values as updated if they have changed and ignoreArrayOrder option is true", () => { + expect( + getListDiff( + [ + { id: 3, name: "nina", hobbies: ["swiming"] }, + { id: 1, name: "joseph", hobbies: ["golf", "fishing"] }, + { id: 2, name: "jack", hobbies: ["coding"] }, + ], + [ + { id: 1, name: "joe", hobbies: ["golf", "fishing"] }, + { id: 2, name: "jack", hobbies: ["coding"] }, + { id: 3, name: "nina", hobbies: ["swiming"] }, + ], + { + ignoreArrayOrder: true, + referenceProperty: "id", + } + ) + ).toStrictEqual({ + type: "list", + status: "updated", + diff: [ + { + value: { id: 1, name: "joe", hobbies: ["golf", "fishing"] }, + prevIndex: 1, + newIndex: 0, + indexDiff: -1, + status: "updated", + }, + { + value: { id: 2, name: "jack", hobbies: ["coding"] }, + prevIndex: 2, + newIndex: 1, + indexDiff: -1, + status: "equal", + }, + { + value: { id: 3, name: "nina", hobbies: ["swiming"] }, + prevIndex: 0, + newIndex: 2, + indexDiff: 2, + status: "equal", + }, + ], + }); + }); });