Browse Source

feat: add ignoreArrayOrder option to getListDiff (#23)

pull/25/head
DoneDeal0 9 months ago committed by GitHub
parent
commit
6daef58adf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      README.md
  2. 3
      package.json
  3. 11
      src/list-diff.ts
  4. 1
      src/model.ts
  5. 91
      test/list-diff.test.ts

4
README.md

@ -8,7 +8,6 @@ This library compares two arrays or objects and returns a full diff of their dif @@ -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 @@ -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**!
<div style="display: flex;>
<a href="https://github.com/AlexisAnzieu" target="_blank"><img alt="AlexisAnzieu" src="https://github.com/DoneDeal0/superdiff/assets/43271780/8e9fb627-36ec-479d-87d4-3ca2cb2a796c" width="72px" height="72px"/></a>
@ -235,11 +233,13 @@ You can add a third `options` parameter to `getListDiff`. @@ -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()

3
package.json

@ -33,7 +33,8 @@ @@ -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",

11
src/list-diff.ts

@ -1,10 +1,4 @@ @@ -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 = <T>( @@ -72,6 +66,7 @@ export const getListDiff = <T>(
showOnly: [],
referenceProperty: undefined,
considerMoveAsUpdate: false,
ignoreArrayOrder: false,
}
): ListDiff => {
if (!prevList && !nextList) {
@ -110,7 +105,7 @@ export const getListDiff = <T>( @@ -110,7 +105,7 @@ export const getListDiff = <T>(
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)) {

1
src/model.ts

@ -55,6 +55,7 @@ export type ListOptions = { @@ -55,6 +55,7 @@ export type ListOptions = {
showOnly?: Array<ListStatusTuple[number]>;
referenceProperty?: string;
considerMoveAsUpdate?: boolean;
ignoreArrayOrder?: boolean;
};
export type ListDiff = {

91
test/list-diff.test.ts

@ -697,4 +697,95 @@ describe("getListDiff", () => { @@ -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",
},
],
});
});
});

Loading…
Cancel
Save