some-common-functions-js 1.1.0 → 1.1.3

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.
Files changed (4) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +182 -46
  3. package/index.js +150 -84
  4. package/package.json +3 -6
package/CHANGELOG.md CHANGED
@@ -33,7 +33,15 @@ Improve README.md documentation.
33
33
  ## Version 1.0.9 - 2025/11/28 - ITA
34
34
  - Provided more documentation in test.js to remind a developer how to symbolic-link (mimick as installed) the package and running the test code.
35
35
  - Added new function, hasOnlyAll(), and updated the README.md documentation accordingly.
36
-
36
+
37
37
  ## Version 1.1.0 - 2025/12/22 - ITA
38
38
  - Improved documentation.
39
39
  - Moved in more functions to the package: `deepClone(anObject)`, `getSortedObject(anObject)`, `timeStampYyyyMmDd(dateInstance)` and `timeStampString(dateInstance)`.
40
+
41
+ ## Version 1.1.1 - 2025/12/26 - ITA
42
+ - Removed lodash dependency and re-implemented the get() and set() object functions, reducing package size.
43
+ - Re-implemented the getSortedObj() function to no longer use the get() object function.
44
+ - Improved the duplicate removal process in getArrayWithNoDuplicates() function, so as to be more reliable across all cases. Implemented the new getNextDifferentObject() function in the light of that.
45
+
46
+ ## Version 1.1.2 - 2025/12/26 - ITA
47
+ Corrected a minor error in the README documentation.
package/README.md CHANGED
@@ -6,16 +6,18 @@ Common functions used for working with JavaScript objects and validating field v
6
6
  ## Installation
7
7
  ```
8
8
  npm install some-common-functions-js
9
- ```
9
+ ```
10
+
10
11
  ## 1. JavaScript Object Utilities
11
-
12
+
12
13
  ### `deepClone(anObject)`
13
- Returns a deep clone of a plain Javascript object. The clone, while it has field equal to that of the original object, is separate from the original object.
14
-
14
+ Returns a deep clone of a plain Javascript object. The clone, while it has field equal to that of the original object, is separate from the original object.
15
+
15
16
  ### `getPaths(anObject)`
16
17
  Returns a string array of path/field names inside a JavaScript object.
18
+
17
19
  ***Example***
18
- ```
20
+ ```
19
21
  const { getPaths } = require("some-common-functions-js");
20
22
  let client = {
21
23
  name: "Jack",
@@ -35,11 +37,14 @@ let client = {
35
37
  let paths = getPaths(client);
36
38
  // ["name", "surname", "address.streetNum", "address.streetName", "address.suburb",
37
39
  // "address.town", "address.country.name", "address.country.code"]
38
- ```
40
+ ```
41
+
39
42
  ### `getSortedObject(anObject)`
40
- Returns an object with sorted fields, by ordered by field name ascending.
41
- ***Examples***
42
- ```
43
+ Returns an object with sorted fields, ordered by field name ascending.
44
+
45
+ ***Examples***
46
+ ```
47
+ const { get } = require("common-functions-js");
43
48
  const client = {
44
49
  firstName: "Isaiah",
45
50
  lastName: "Tshabalala",
@@ -74,11 +79,90 @@ const sortedObject = getSortedObject(client);
74
79
  lastName: 'Tshabalala'
75
80
  }
76
81
  */
77
- ```
82
+ ```
83
+
84
+ ### `get(anObject, path)`
85
+ Returns the value of an object at the specified path.
86
+ Can take the place of lodash get() function.
87
+
88
+ ***Examples***
89
+ ```
90
+ const { get } = require("some-common-functions-js");
91
+ const client = {
92
+ firstName: "Isaiah",
93
+ lastName: "Tshabalala",
94
+ address: {
95
+ houseNum: "5520",
96
+ streetName: "Main Road",
97
+ mainPlace: "Evaton",
98
+ subPlace: "Evaton Small Farms",
99
+ city: "Vereeniging",
100
+ country: {
101
+ name: "South Africa",
102
+ code: "ZA"
103
+ }
104
+ }
105
+ };
106
+
107
+ let result = get(client, "address.country");
108
+ // { name: "South Africa", code: "ZA" }
109
+
110
+ result = get(client, "address.country.code");
111
+ // "ZA"
112
+ ```
113
+
114
+ ### `set(anObject, path)`
115
+ Sets the value of an object at the specified path.
116
+ Can take the place of lodash set() function.
117
+
118
+ ***Examples***
119
+ ```
120
+ const { set } = require("some-common-functions-js");
121
+
122
+ let emptyObj = {};
123
+ set(emptyObj, "address.country.name", "South Africa");
124
+ set(emptyObj, "address.country.code", "ZA");
125
+ set(emptyObj, "firstName", "Isaiah");
126
+ set(emptyObj, "lastName", "Tshabalala");
127
+ console.log(emptyObj);
128
+ /*
129
+ {
130
+ address: { country: { name: 'South Africa', code: 'ZA' } },
131
+ firstName: 'Isaiah',
132
+ lastName: 'Tshabalala'
133
+ }
134
+ */
135
+ ```
136
+
137
+ ### `unset(anObject, path)`
138
+ Remove a field from an object at the specified path.
139
+ Can take the place of lodash unset() function.
140
+
141
+ ***Example***
142
+ ```
143
+ const {unset} = require("some-common-functions-js");
144
+ let testObj = {
145
+ firstName: 'John',
146
+ lastName: 'Rambo',
147
+ address: { country: { name: 'South Africa', code: 'ZA' } }
148
+ };
149
+
150
+ unset(testObj, "address.country.code");
151
+ unset(testObj, "lastName");
152
+ console.log(testObj); // Expecting to have "address.country.code" and "lastName" removed.
153
+ /*
154
+ {
155
+ firstName: 'John',
156
+ address: { country: { name: 'South Africa' } }
157
+ }
158
+ */
159
+ ```
160
+
78
161
  ### `hasOnly(anObject, ...fields)`
79
162
  Returns `true` if the object contains **only** some or all of the specified fields and no others.
163
+
80
164
  ***Examples***
81
- ```
165
+ ```
82
166
  const { hasOnly } = require("some-common-functions-js");
83
167
 
84
168
  let car = {
@@ -97,12 +181,14 @@ result = hasOnly(car, "maxSpeed", "gvm", "power");
97
181
 
98
182
  result = hasOnly(car, "make", "model");
99
183
  // false, because car has fields other than the specified fields.
100
- ```
184
+ ```
185
+
101
186
  ### `hasAll(anObject, ...fields)`
102
187
  Returns `true` if the object contains **all** the specified fields.
103
188
  The object may contain additional fields.
189
+
104
190
  ***Examples***
105
- ```
191
+ ```
106
192
  const { hasAll } = require("some-common-functions-js");
107
193
  let car = {
108
194
  make: "Ford",
@@ -116,11 +202,13 @@ let result = hasAll(car, "make", "model");
116
202
 
117
203
  let result = hasAll(car, "passengerCapacity", "year");
118
204
  // false, because car does not have "passengerCapacity" field.
119
- ```
205
+ ```
206
+
120
207
  ### `hasOnlyAll(anObject, ...fields)`
121
- Return `true` if an object contains only all the specified fields, nothing more, nothing less
122
- ***Example***
123
- ```
208
+ Return `true` if an object contains only all the specified fields, nothing more, nothing less
209
+
210
+ ***Examples***
211
+ ```
124
212
  const { hasOnlyAll } = require("some-common-functions-js");
125
213
  let car = {
126
214
  make: "Ford",
@@ -327,20 +415,16 @@ console.log(objArray);
327
415
  */
328
416
  let teams = [
329
417
  {
330
- score: 85,
331
- numGames: 10
418
+ score: 85, numGames: 10
332
419
  },
333
420
  {
334
- score: 90,
335
- numGames: 12
421
+ score: 90, numGames: 12
336
422
  },
337
423
  {
338
- score: 85,
339
- numGames: 8
424
+ score: 85, numGames: 8
340
425
  },
341
426
  {
342
- score: 90,
343
- numGames: 10
427
+ score: 90, numGames: 10
344
428
  }
345
429
  ];
346
430
  // Using objCompare to sort fields where there are mixed sort directions.
@@ -396,35 +480,84 @@ Create an array of objects with duplicates eliminated. Taking only the first or
396
480
  * The value of the comparison field must include both the field name and sort direction.
397
481
  * Sort direction assumed to be "asc" if not provided.
398
482
  * Examples of comparison fields: "firstName", "lastName desc", "address.province asc", "address.townOrCity".
399
-
483
+
400
484
  ***Example***
401
485
  ```
402
486
  const { getObjArrayWithNoDuplicates } = require("some-common-functions-js");
403
- let teamsArray = [
404
- { score: 90, numGames: 10 },
405
- { score: 90, numGames: 10 },
406
- { score: 90, numGames: 10 },
407
- { score: 90, numGames: 12 },
408
- { score: 90, numGames: 12 },
409
- { score: 90, numGames: 12 },
410
- { score: 85, numGames: 8 },
411
- { score: 85, numGames: 8 },
412
- { score: 85, numGames: 10 },
413
- { score: 85, numGames: 10 },
414
- { score: 85, numGames: 10 }
487
+ let teamsArray = [
488
+ { score: 90, numGames: 10, name: "John" },
489
+ { score: 90, numGames: 10, name: "Jane" },
490
+ { score: 90, numGames: 10, name: "Bob" },
491
+ { score: 90, numGames: 12, name: "Alice" },
492
+ { score: 90, numGames: 12, name: "Charlie" },
493
+ { score: 90, numGames: 12, name: "David" },
494
+ { score: 85, numGames: 8, name: "Eve" },
495
+ { score: 85, numGames: 8, name: "Frank" },
496
+ { score: 85, numGames: 10, name: "Grace" },
497
+ { score: 85, numGames: 10, name: "Henry" },
498
+ { score: 85, numGames: 10, name: "Ivy" }
415
499
  ]; // Sorted by "score desc", "numGames asc".
416
500
 
417
501
  let noDuplicatesArray = getObjArrayWithNoDuplicates(teamsArray, true, "score desc", "numGames asc");
418
- console.log(noDuplicatesArray); // Should contain only unique objects according to comparison fields.
502
+ console.log(noDuplicatesArray);
503
+ // Should contain only unique objects according to comparison fields. First object per duplicate group.
419
504
  /*
420
- [
421
- { score: 90, numGames: 10 },
422
- { score: 90, numGames: 12 },
423
- { score: 85, numGames: 8 },
424
- { score: 85, numGames: 10 }
425
- ]
505
+ [
506
+ { score: 90, numGames: 10, name: 'John' },
507
+ { score: 90, numGames: 12, name: 'Alice' },
508
+ { score: 85, numGames: 8, name: 'Eve' },
509
+ { score: 85, numGames: 10, name: 'Grace' }
510
+ ]
426
511
  */
427
- ```
512
+
513
+ let noDuplicatesArray = getObjArrayWithNoDuplicates(teamsArray, true, "score desc", "numGames asc");
514
+ console.log(noDuplicatesArray);
515
+ // Should contain unique objects according to comparison fields. Last object per duplicate group.
516
+ /*
517
+ [
518
+ { score: 90, numGames: 10, name: 'Bob' },
519
+ { score: 90, numGames: 12, name: 'David' },
520
+ { score: 85, numGames: 8, name: 'Frank' },
521
+ { score: 85, numGames: 10, name: 'Ivy' }
522
+ ]
523
+ */
524
+ ```
525
+
526
+ ### `getNextDifferent(objArray, targetObj, startFrom, ...comparisonFields)`
527
+ Get the index in the array of objects, of the next element that is distinct from the target object.
528
+ Comparison fields must match the field & sort order of the object array.
529
+ Throw an error if the target object is greater than objArray[startFrom] in terms of sort order.
530
+ Examples of comparison fields: "firstName", "lastName desc", "address.province asc", "address.townOrCity".
531
+
532
+ ***Example***
533
+ ```
534
+ const { getNextDifferent } = require("some-common-functions-js");
535
+
536
+ teamsArray = [
537
+ { score: 90, numGames: 10, name: "John" },
538
+ { score: 90, numGames: 10, name: "Jane" },
539
+ { score: 90, numGames: 10, name: "Bob" },
540
+ { score: 90, numGames: 12, name: "Alice" },
541
+ { score: 90, numGames: 12, name: "Charlie" },
542
+ { score: 90, numGames: 12, name: "David" },
543
+ { score: 85, numGames: 8, name: "Eve" },
544
+ { score: 85, numGames: 8, name: "Frank" },
545
+ { score: 85, numGames: 10, name: "Grace" },
546
+ { score: 85, numGames: 10, name: "Henry" },
547
+ { score: 85, numGames: 10, name: "Ivy" }
548
+ ]; // Sorted by "score desc", "numGames asc".
549
+
550
+ let next = getNextDifferent(teamsArray, { score: 85, numGames: 8 }, 0, "score desc", "numGames asc");
551
+ // Throws an error because the startFrom index is to the left ('less than') the target object in terms of the field sort order.
552
+
553
+ next = getNextDifferent(teamsArray, { score: 90, numGames: 10 }, 0, "score desc", "numGames asc");
554
+ // 3
555
+
556
+
557
+ next = getNextDifferentObj(teamsArray, { score: 85, numGames: 10 }, 0, "score desc", "numGames asc");
558
+ // -1
559
+ ```
560
+
428
561
  ## 4. Date Timestamp Functions
429
562
  ### `timeStampYyyyMmDd(dateInstance)`
430
563
  Converts the date object to a string of the form CCYY-MM-DD
@@ -432,6 +565,9 @@ Converts the date object to a string of the form CCYY-MM-DD
432
565
  ### `timeStampString(dateInstance)`
433
566
  Converts a date object to a string of the form CCYY-MM-DDThh:mm:ss.ccc, e.g. '2024-02-25T15:00:25.251'
434
567
 
568
+ ### `addLeadingZeros(aNumber, newLength)`
569
+ Add leading zeros to a numerical string. E.g. addLeadingZeros(9, 3) = '009'
570
+
435
571
  ---
436
572
  ## License
437
573
  MIT
package/index.js CHANGED
@@ -4,8 +4,11 @@
4
4
  * 2025/11/19 ITA 1.00 Genesis.
5
5
  * 2025/11/28 ITA 1.01 Added function hasOnlyAll().
6
6
  * 2025/12/22 ITA 1.02 Improved documentation of the functions and moved in more functions.
7
+ * 2025/12/30 ITA 1.03 Removed lodash dependency by re-implementing get() and set() object functions, significantly reducing this package size.
8
+ * Added function getNextDifferent() to deal better with duplicate removal from arrays of objects.
9
+ * 2026/01/02 ITA 1.04 Improved the functions getNoDuplicatesArray() and getNextDifferent() to handle more test cases.
10
+ * Added function unset().
7
11
  */
8
- const loDash = require('lodash');
9
12
 
10
13
  /**Return true if userName is valid
11
14
  * @param {string} userName
@@ -203,27 +206,101 @@ function getPaths(anObject) {
203
206
  } // function getPaths()
204
207
  module.exports.getPaths = getPaths;
205
208
 
206
- /** Return an object with sorted fields, by ordered by field name ascending.
209
+ /** Return an object with sorted fields, ordered by field name ascending.
207
210
  * This is desirable when equality comparison is done to ensure two objects sharing equal field values
208
211
  * the pass the equality test stringify(object1) === stringify(object2)
209
212
  * @param {object} pObject
210
213
  * @returns {object} an object with fields sorted in ascending order of field names.
211
214
  */
212
215
  function getSortedObject(pObject) {
216
+ const objClone = deepClone(pObject);
217
+ const paths = [];
218
+ const sortedObject = {};
213
219
 
214
- const paths = getPaths(pObject);
220
+ // Obtain the outermost fields and sort them.
221
+ for (let field in objClone) {
222
+ paths.push(field);
223
+ }
215
224
  paths.sort();
216
- const sortedObject = {};
217
225
 
226
+ // Assign the sorted fields to the new object.
218
227
  for (let index in paths) {
219
- const path = paths[index];
220
- const value = loDash.get(pObject, path);
221
- loDash.set(sortedObject, path, value);
222
- } // for (index in paths) {
228
+ const field = paths[index];
229
+ if (Object.prototype.toString.call(objClone[field]) === '[object Object]') {
230
+ sortedObject[field] = getSortedObject(objClone[field]);
231
+ }
232
+ else {
233
+ sortedObject[field] = objClone[field];
234
+ } //
235
+ } // for (let field in paths) {
236
+
223
237
  return sortedObject;
224
238
  } // function getSortedObject(pObject) {
225
239
  module.exports.getSortedObject = getSortedObject;
226
240
 
241
+ /** Get the value of a field specified by the path from an object.
242
+ * @param {object} anObject a Javascript object.
243
+ * @param {string} path a path specifying the field whose value is to be obtained.
244
+ * @returns {*} the value of the field specified by the path.
245
+ */
246
+ function get(anObject, path) {
247
+ if (getPaths(anObject).includes(path) === false) {
248
+ console.log(hasAll(anObject, path), path, anObject, getPaths(anObject));
249
+ throw new Error(`Path ${path} does not exist on the object.`);
250
+ }
251
+ let paths = path.split('.');
252
+ let currentObj = deepClone(anObject);
253
+
254
+ let value = currentObj[paths[0]];
255
+ if (paths.length > 1) {
256
+ paths.splice(0, 1);
257
+ return get(value, paths.join('.'));
258
+ }
259
+ else {
260
+ return value;
261
+ }
262
+ }
263
+ module.exports.get = get;
264
+
265
+ /** Set the value of a field specified by the path on an object.
266
+ * @param {object} anObject a Javascript object.
267
+ * @param {string} path a path specifying the field whose value is to be set.
268
+ * @param {*} value the value to set.
269
+ */
270
+ function set(anObject, path, value) {
271
+ let paths = path.split('.');
272
+ if (paths.length > 1) {
273
+ if (!anObject[paths[0]]) {
274
+ anObject[paths[0]] = {};
275
+ }
276
+ const subObject = anObject[paths[0]];
277
+ paths.splice(0, 1);
278
+ set(subObject, paths.join('.'), value);
279
+ }
280
+ else {
281
+ anObject[paths[0]] = value;
282
+ }
283
+ }
284
+ module.exports.set = set;
285
+
286
+ /** Unset the value of a field specified by the path on an object.
287
+ * @param {object} anObject a Javascript object.
288
+ * @param {string} path a path specifying the field whose value is to be set.
289
+ * @param {*} value the value to set.
290
+ */
291
+ function unset(anObject, path) {
292
+ let paths = path.split('.');
293
+ if (paths.length > 1) {
294
+ const subObject = anObject[paths[0]];
295
+ paths.splice(0, 1);
296
+ unset(subObject, paths.join('.'));
297
+ }
298
+ else {
299
+ delete anObject[paths[0]];
300
+ }
301
+ }
302
+ module.exports.unset = unset;
303
+
227
304
  /**
228
305
  * Determine whether an object contains only 1, some or all of the specified fields, and not any other fields.
229
306
  * @param {object} anObject a Javascript object.
@@ -393,6 +470,42 @@ function binarySearchObj(objArray, searchObj, startFrom = 0, ...sortFields) {
393
470
  } // function binarySearchObj(objArray, searchObj, ...comparisonFields) {
394
471
  module.exports.binarySearchObj = binarySearchObj;
395
472
 
473
+ /**Get the index of the first element in an object array that is different from the target element
474
+ * according to the comparison fields.
475
+ * @param {Array<object>} objArray an array of objects
476
+ * @param {object} targetObj target object
477
+ * @param {number} startFrom index from which to start searching
478
+ * @param {...string} comparisonFields comparison fields plus sort order.
479
+ * @returns index of the next different object.
480
+ */
481
+ function getNextDifferent(objArray, targetObj, startFrom, ...comparisonFields) {
482
+ let start = startFrom,
483
+ end = objArray.length - 1;
484
+
485
+
486
+ if (start >= objArray.length) { // throw error if startFrom is outside the bounds of the array.
487
+ throw new Error('startFrom is outside the bounds of the array.');
488
+ }
489
+ // If target object is to the right of objArray[start], then throw an error..
490
+ if (objCompare(targetObj, objArray[start], ...comparisonFields) > 0) {
491
+ throw new Error('targetObj is to the right (\'greater than\') objArray[startFrom].');
492
+ }
493
+
494
+ while (start < end) {
495
+ let mid = Math.trunc((start + end) / 2);
496
+ if (objCompare(targetObj, objArray[mid], ...comparisonFields) === 0) {
497
+ start = mid + 1;
498
+ }
499
+ else if (objCompare(targetObj, objArray[mid], ...comparisonFields) < 0) {
500
+ end = mid;
501
+ }
502
+ }
503
+ if (objCompare(targetObj, objArray[start], ...comparisonFields) === 0)
504
+ return -1;
505
+ return start;
506
+ }
507
+ module.exports.getNextDifferent = getNextDifferent;
508
+
396
509
  /**Create an array with duplicates eliminated, according to certain fields. Taking only the first or last object from each duplicate set.
397
510
  * If firstOfDuplicates === true, then the first element in each set of duplicates is taken.
398
511
  * if firstOfDuplicates === false, then the last element is taken from each set of duplicates.
@@ -407,89 +520,42 @@ module.exports.binarySearchObj = binarySearchObj;
407
520
  * @returns {Array<object>} an array with no duplicates.
408
521
  */
409
522
  function getObjArrayWithNoDuplicates(objArray, firstOfDuplicates, ...comparisonFields) {
410
- function getNextSearchObj(pNext) {
411
- const nextObj = {...objArray[next]};
412
- let lastField;
413
- if (comparisonFields.length > 0)
414
- lastField = comparisonFields[comparisonFields.length - 1].split(' ');
415
- else
416
- throw new Error('Supply atleast 1 comparisonFields parameter.');
417
-
418
- const lastFieldName = lastField[0];
419
- const sortDir = lastField.length > 1? lastField[1] : 'asc';
420
- const lastFieldValue = loDash.get(nextObj, lastFieldName);
421
-
422
- if (typeof lastFieldValue === 'number') {
423
- if (sortDir === 'asc')
424
- loDash.set(nextObj, lastFieldName, 1e-10 + lastFieldValue);
425
- else
426
- loDash.set(nextObj, lastFieldName, -1e-10 + lastFieldValue);
427
- }
428
- else if (typeof lastFieldValue === 'string') { // instance of String
429
- if (sortDir === 'asc')
430
- loDash.set(nextObj, lastFieldName, lastFieldValue + ' ');
431
- else
432
- loDash.set(nextObj, lastFieldName, ' ' + lastFieldValue);
433
- }
434
- else if (lastFieldValue instanceof Date) {
435
- if (sortDir === 'asc')
436
- loDash.set(nextObj, lastFieldName, new Date(1 + lastFieldValue.getTime()));
437
- else
438
- loDash.set(nextObj, lastFieldName, new Date(-1 + lastFieldValue.getTime()));
439
- }
440
- else
441
- throw new Error(`${lastFieldName} must be type Number, String or Date`);
442
-
443
- return nextObj;
444
- } // function getNextSearchObj(pNext)
445
523
 
446
524
  if (objArray.length <= 1)
447
525
  return [...objArray];
448
526
 
449
- if (![true, false].includes(firstOfDuplicates))
450
- throw new Error(`firstOfDuplicates must be one of ${[true, false]}`);
527
+ if (typeof firstOfDuplicates !== 'boolean')
528
+ throw new Error(`firstOfDuplicates must be boolean true or false.`);
451
529
 
452
530
  const noDuplicates = [];
531
+ let idx = 0;
532
+ let grpStart = 0; // Start index of current duplicate group.
533
+ while (grpStart < objArray.length - 1) {
534
+ if (firstOfDuplicates) {
535
+ noDuplicates.push(objArray[grpStart]);
536
+ }
537
+
538
+ grpStart = getNextDifferent(objArray, objArray[grpStart], grpStart + 1, ...comparisonFields);
539
+ if (grpStart < 0)
540
+ break; // No more different objects.
453
541
 
454
- let next = 0;
455
- let nextSearchObj;
456
- if ((firstOfDuplicates)) {
457
- noDuplicates.push(objArray[next]);
458
- }
459
- nextSearchObj = getNextSearchObj(objArray[next]);
460
-
461
- while (next < objArray.length) {
462
- // The aim is to jump to the next element that is not a duplicate of objArray[next].
463
- next = binarySearchObj(objArray, nextSearchObj, next, ...comparisonFields);
464
- let comparison = objCompare(objArray[next], nextSearchObj, ...comparisonFields);
465
- if (comparison < 0) {
466
- if (firstOfDuplicates) {
467
- next++;
468
- if (next < objArray.length) {
469
- noDuplicates.push(objArray[next]);
470
- nextSearchObj = getNextSearchObj(objArray[next]);
471
- }
472
- }
473
- else {
474
- noDuplicates.push(objArray[next]);
475
- next++;
476
- if (next < objArray.length)
477
- nextSearchObj = getNextSearchObj(objArray[next]);
478
- }
479
- continue;
542
+ let grpEnd = grpStart - 1;
543
+ if (!firstOfDuplicates) {
544
+ noDuplicates.push(objArray[grpEnd]);
480
545
  }
481
- else {
482
- if (!firstOfDuplicates) {
483
- noDuplicates.push(objArray[next]);
484
- }
485
- else {
486
- noDuplicates.push(objArray[next]);
487
- }
546
+ idx = grpStart;
547
+ }
548
+ if (noDuplicates.length === 0) { // All objects are duplicates.
549
+ if (firstOfDuplicates)
550
+ noDuplicates.push(objArray[0]);
551
+ else
552
+ noDuplicates.push(objArray[objArray.length - 1]);
553
+ }
554
+ else {
555
+ if (objCompare(noDuplicates[noDuplicates.length - 1], objArray[objArray.length - 1], ...comparisonFields) !== 0) {
556
+ noDuplicates.push(objArray[objArray.length - 1]);
488
557
  }
489
-
490
- nextSearchObj = getNextSearchObj(objArray[next]);
491
- next++;
492
- } // while (comparison !== 0 && next < objArray.length) {
558
+ }
493
559
 
494
560
  return noDuplicates;
495
561
  } // function getObjArrayWithNoDuplicates(objArray, ...comparisonFields) {
@@ -519,8 +585,8 @@ function objCompare(obj1, obj2, ...comparisonFields) {
519
585
  if (!sortDirections.includes(sortDir))
520
586
  throw new Error('Sort direction must be one of ' + sortDirections.toString());
521
587
 
522
- const value1 = loDash.get(obj1, fieldName);
523
- const value2 = loDash.get(obj2, fieldName);
588
+ const value1 = get(obj1, fieldName);
589
+ const value2 = get(obj2, fieldName);
524
590
 
525
591
  const returnValue = (sortDir === 'desc'? -1: 1);
526
592
  if (value1 > value2)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "some-common-functions-js",
3
- "version": "1.1.0",
3
+ "version": "1.1.3",
4
4
  "description": "Common functions used with Javascript objects, and field validation functions.",
5
5
  "keywords": [
6
6
  "validation",
@@ -23,21 +23,18 @@
23
23
  "object utilities",
24
24
  "object validation",
25
25
  "object array search",
26
- "object compaare",
26
+ "object compare",
27
27
  "nodejs"
28
28
  ],
29
29
  "repository": {
30
30
  "type": "git",
31
31
  "url": "https://github.com/IsaiahTshabalala/common-functions"
32
32
  },
33
- "license": "ISC",
33
+ "license": "MIT",
34
34
  "author": "ITA",
35
35
  "type": "commonjs",
36
36
  "main": "index.js",
37
37
  "scripts": {
38
38
  "test": "echo \"Error: no test specified\" && exit 1"
39
- },
40
- "dependencies": {
41
- "lodash": "^4.17.21"
42
39
  }
43
40
  }