@tim-code/my-util 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tim-code/my-util",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "author": "Tim Sprowl",
package/src/array.js CHANGED
@@ -20,12 +20,38 @@ export function chunk(array, chunkSize = array.length) {
20
20
  }
21
21
 
22
22
  /**
23
- * Shorthand for returning all unique elements in an array.
23
+ * Returns all unique elements in an array, or alternatively by checking a key's value or function's result.
24
24
  * @param {Array} array
25
+ * @param {Object} $1
26
+ * @param {string|number|Function=} $1.key
27
+ * If a function, calls the provided function on an element to get the value to check for uniqueness.
28
+ * If a string or number, checks each element's value at key for uniqueness.
25
29
  * @returns {Array}
26
30
  */
27
- export function unique(array) {
28
- return [...new Set(array)]
31
+ export function unique(array, { key } = {}) {
32
+ const seen = new Set()
33
+ const result = []
34
+ if (typeof key === "function") {
35
+ for (let i = 0; i < array.length; i++) {
36
+ const element = array[i]
37
+ const value = key(element, i, array)
38
+ if (!seen.has(value)) {
39
+ seen.add(value)
40
+ result.push(element)
41
+ }
42
+ }
43
+ } else if (typeof key === "string" || typeof key === "number") {
44
+ for (const element of array) {
45
+ const value = element[key]
46
+ if (!seen.has(value)) {
47
+ seen.add(value)
48
+ result.push(element)
49
+ }
50
+ }
51
+ } else {
52
+ return [...new Set(array)]
53
+ }
54
+ return result
29
55
  }
30
56
 
31
57
  // sorts undefined and null to the end if applicable
package/src/array.test.js CHANGED
@@ -68,6 +68,98 @@ describe("unique", () => {
68
68
  const b = {}
69
69
  expect(unique([a, b, a])).toEqual([a, b])
70
70
  })
71
+
72
+ it("returns unique elements by key (string)", () => {
73
+ const arr = [
74
+ { id: 1, name: "a" },
75
+ { id: 2, name: "b" },
76
+ { id: 1, name: "c" },
77
+ { id: 3, name: "d" },
78
+ { id: 2, name: "e" },
79
+ ]
80
+ expect(unique(arr, { key: "id" })).toEqual([
81
+ { id: 1, name: "a" },
82
+ { id: 2, name: "b" },
83
+ { id: 3, name: "d" },
84
+ ])
85
+ })
86
+
87
+ it("returns unique elements by key (number)", () => {
88
+ const arr = [
89
+ { 0: "a", v: 1 },
90
+ { 0: "b", v: 2 },
91
+ { 0: "a", v: 3 },
92
+ { 0: "c", v: 4 },
93
+ ]
94
+ expect(unique(arr, { key: 0 })).toEqual([
95
+ { 0: "a", v: 1 },
96
+ { 0: "b", v: 2 },
97
+ { 0: "c", v: 4 },
98
+ ])
99
+ })
100
+
101
+ it("returns unique elements by function", () => {
102
+ const arr = [
103
+ { id: 1, name: "a" },
104
+ { id: 2, name: "b" },
105
+ { id: 1, name: "c" },
106
+ { id: 3, name: "d" },
107
+ { id: 2, name: "e" },
108
+ ]
109
+ expect(
110
+ unique(arr, {
111
+ key: (el) => el.id % 2, // group by odd/even id
112
+ })
113
+ ).toEqual([
114
+ { id: 1, name: "a" }, // id % 2 === 1
115
+ { id: 2, name: "b" }, // id % 2 === 0
116
+ ])
117
+ })
118
+
119
+ it("returns unique elements by function using index and array", () => {
120
+ const arr = ["a", "b", "c", "a"]
121
+ expect(
122
+ unique(arr, {
123
+ key: (el, i, array) => array.indexOf(el), // only first occurrence is unique
124
+ })
125
+ ).toEqual(["a", "b", "c"])
126
+ })
127
+
128
+ it("returns unique elements by key when some elements lack the key", () => {
129
+ const arr = [{ id: 1 }, {}, { id: 1 }, { id: 2 }, {}]
130
+ expect(unique(arr, { key: "id" })).toEqual([{ id: 1 }, {}, { id: 2 }])
131
+ })
132
+
133
+ it("returns unique elements by function when function returns undefined/null", () => {
134
+ const arr = [{ id: 1 }, {}, { id: 2 }, { id: null }, {}]
135
+ expect(
136
+ unique(arr, {
137
+ key: (el) => el.id,
138
+ })
139
+ ).toEqual([{ id: 1 }, {}, { id: 2 }, { id: null }])
140
+ })
141
+
142
+ it("returns unique elements by key when key value is undefined/null", () => {
143
+ const arr = [{ id: 1 }, { id: undefined }, { id: 2 }, { id: null }, { id: undefined }]
144
+ expect(unique(arr, { key: "id" })).toEqual([
145
+ { id: 1 },
146
+ { id: undefined },
147
+ { id: 2 },
148
+ { id: null },
149
+ ])
150
+ })
151
+
152
+ it("returns unique elements for primitive array if key is not provided", () => {
153
+ expect(unique([1, 2, 2, 3], {})).toEqual([1, 2, 3])
154
+ expect(unique([1, 2, 2, 3], { key: undefined })).toEqual([1, 2, 3])
155
+ })
156
+
157
+ it("returns unique elements for object array if key is not provided", () => {
158
+ const a = { x: 1 }
159
+ const b = { x: 2 }
160
+ expect(unique([a, b, a], {})).toEqual([a, b])
161
+ expect(unique([a, b, a], { key: undefined })).toEqual([a, b])
162
+ })
71
163
  })
72
164
 
73
165
  describe("ascending", () => {