Skip to content

Commit 2f9bed7

Browse files
author
DoneDeal0
authored
Merge pull request #7 from DoneDeal0/handle-duplicate-values-in-arrays
feat: support duplicated values in arrays
2 parents d77ef7c + ad7431f commit 2f9bed7

File tree

3 files changed

+182
-8
lines changed

3 files changed

+182
-8
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ Compares two arrays and return a diff for each value:
178178
- index change: `prevIndex`, `newIndex`, `indexDiff`
179179
- status: `added`, `deleted`, `equal`, `moved`, `updated`
180180
- value
181-
- supports array of primitive values and objects
182-
- ⚠️ doesn't support duplicated values comparison yet (but will soon)
181+
- supports arrays of primitive values and objects
182+
- supports arrays with duplicated values
183183

184184
format:
185185

src/list-diff.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,15 @@ export const getListDiff = (
4242
return formatSingleListDiff(prevList as ListData, STATUS.DELETED);
4343
}
4444
const diff: ListDiff["diff"] = [];
45+
const prevIndexMatches: number[] = [];
4546
nextList.forEach((nextValue, i) => {
46-
const prevIndex = prevList.findIndex((prevValue) =>
47-
isEqual(prevValue, nextValue)
47+
const prevIndex = prevList.findIndex(
48+
(prevValue, prevIdx) =>
49+
isEqual(prevValue, nextValue) && !prevIndexMatches.includes(prevIdx)
4850
);
51+
if (prevIndex > -1) {
52+
prevIndexMatches.push(prevIndex);
53+
}
4954
const indexDiff = prevIndex === -1 ? null : i - prevIndex;
5055
if (indexDiff === 0) {
5156
return diff.push({
@@ -75,7 +80,7 @@ export const getListDiff = (
7580
});
7681

7782
prevList.forEach((prevValue, i) => {
78-
if (!nextList.some((nextValue) => isEqual(nextValue, prevValue))) {
83+
if (!prevIndexMatches.includes(i)) {
7984
return diff.splice(i, 0, {
8085
value: prevValue,
8186
prevIndex: i,

test/list-diff.test.ts

Lines changed: 172 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe("getListDiff", () => {
8484
],
8585
});
8686
});
87-
it("detects changed values in a string list", () => {
87+
it("detects changes between string lists", () => {
8888
expect(
8989
getListDiff(
9090
["mbappe", "mendes", "verratti", "ruiz"],
@@ -132,7 +132,7 @@ describe("getListDiff", () => {
132132
],
133133
});
134134
});
135-
it("detects changed values in a number list", () => {
135+
it("detects changes between number lists", () => {
136136
expect(getListDiff([54, 234, 76, 0], [54, 200, 0])).toStrictEqual({
137137
type: "list",
138138
status: "updated",
@@ -175,7 +175,7 @@ describe("getListDiff", () => {
175175
],
176176
});
177177
});
178-
it("detects changed values in an object list", () => {
178+
it("detects changes between object lists", () => {
179179
expect(
180180
getListDiff(
181181
[
@@ -224,4 +224,173 @@ describe("getListDiff", () => {
224224
],
225225
});
226226
});
227+
it("detects changes between lists containing duplicated values", () => {
228+
expect(
229+
getListDiff(["mbappe", "messi"], ["mbappe", "mbappe", "messi"])
230+
).toStrictEqual({
231+
type: "list",
232+
status: "updated",
233+
diff: [
234+
{
235+
value: "mbappe",
236+
prevIndex: 0,
237+
newIndex: 0,
238+
indexDiff: 0,
239+
status: "equal",
240+
},
241+
{
242+
value: "mbappe",
243+
prevIndex: null,
244+
newIndex: 1,
245+
indexDiff: null,
246+
status: "added",
247+
},
248+
{
249+
value: "messi",
250+
prevIndex: 1,
251+
newIndex: 2,
252+
indexDiff: 1,
253+
status: "moved",
254+
},
255+
],
256+
});
257+
expect(
258+
getListDiff(
259+
["mbappe", "messi", "messi", "mbappe"],
260+
["mbappe", "messi", "messi"]
261+
)
262+
).toStrictEqual({
263+
type: "list",
264+
status: "updated",
265+
diff: [
266+
{
267+
value: "mbappe",
268+
prevIndex: 0,
269+
newIndex: 0,
270+
indexDiff: 0,
271+
status: "equal",
272+
},
273+
{
274+
value: "messi",
275+
prevIndex: 1,
276+
newIndex: 1,
277+
indexDiff: 0,
278+
status: "equal",
279+
},
280+
{
281+
value: "messi",
282+
prevIndex: 2,
283+
newIndex: 2,
284+
indexDiff: 0,
285+
status: "equal",
286+
},
287+
{
288+
value: "mbappe",
289+
prevIndex: 3,
290+
newIndex: null,
291+
indexDiff: null,
292+
status: "deleted",
293+
},
294+
],
295+
});
296+
expect(
297+
getListDiff(
298+
[
299+
false,
300+
true,
301+
true,
302+
undefined,
303+
"hello",
304+
{ name: "joe", age: 88 },
305+
false,
306+
13,
307+
],
308+
[
309+
false,
310+
false,
311+
true,
312+
undefined,
313+
"hello",
314+
{ name: "joe", age: 88 },
315+
false,
316+
{ name: "joe", age: 88 },
317+
]
318+
)
319+
).toStrictEqual({
320+
type: "list",
321+
status: "updated",
322+
diff: [
323+
{
324+
value: false,
325+
prevIndex: 0,
326+
newIndex: 0,
327+
indexDiff: 0,
328+
status: "equal",
329+
},
330+
{
331+
value: false,
332+
prevIndex: 6,
333+
newIndex: 1,
334+
indexDiff: -5,
335+
status: "moved",
336+
},
337+
{
338+
value: true,
339+
prevIndex: 2,
340+
newIndex: null,
341+
indexDiff: null,
342+
status: "deleted",
343+
},
344+
{
345+
value: true,
346+
prevIndex: 1,
347+
newIndex: 2,
348+
indexDiff: 1,
349+
status: "moved",
350+
},
351+
{
352+
value: undefined,
353+
prevIndex: 3,
354+
newIndex: 3,
355+
indexDiff: 0,
356+
status: "equal",
357+
},
358+
{
359+
value: "hello",
360+
prevIndex: 4,
361+
newIndex: 4,
362+
indexDiff: 0,
363+
status: "equal",
364+
},
365+
{
366+
value: { name: "joe", age: 88 },
367+
prevIndex: 5,
368+
newIndex: 5,
369+
indexDiff: 0,
370+
status: "equal",
371+
},
372+
{
373+
value: 13,
374+
prevIndex: 7,
375+
newIndex: null,
376+
indexDiff: null,
377+
status: "deleted",
378+
},
379+
{
380+
value: false,
381+
prevIndex: null,
382+
newIndex: 6,
383+
indexDiff: null,
384+
status: "added",
385+
},
386+
{
387+
value: { name: "joe", age: 88 },
388+
prevIndex: null,
389+
newIndex: 7,
390+
indexDiff: null,
391+
status: "added",
392+
},
393+
],
394+
});
395+
});
227396
});

0 commit comments

Comments
 (0)