-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharrayCompare.ts
121 lines (103 loc) · 3.1 KB
/
arrayCompare.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*!
* @author electricessence / https://github.com/electricessence/
* @license MIT
*/
import areEqualValue from '@tsdotnet/compare/dist/areEqual';
import ArgumentNullException from '@tsdotnet/exceptions/dist/ArgumentNullException';
import ArgumentException from '@tsdotnet/exceptions/dist/ArgumentException';
import {Comparison, EqualityComparison} from '@tsdotnet/compare/dist/Comparable';
import type from '@tsdotnet/type';
import compare from '@tsdotnet/compare/dist/compare';
/* validateSize: Utility for quick validation/invalidation of array equality.
Why this way? Why not pass a closure for the last return?
Reason: Performance and avoiding the creation of new functions/closures. */
function validateSize (a: ArrayLike<any>, b: ArrayLike<any>): boolean | number
{
// Both valid and are same object, or both are null/undefined.
if((a && b && a===b) || (!a && !b)) return true;
// At this point, at least one has to be non-null.
if(!a || !b) return false;
const len = a.length;
if(len!==b.length) return false;
// If both are arrays and have zero length, they are equal.
if(len===0) return true;
// Return the length for downstream processing.
return len;
}
export function areAllEqual (
arrays: ArrayLike<ArrayLike<any>>,
equalityComparison: EqualityComparison<any> = areEqualValue
): boolean
{
if(!arrays) throw new ArgumentNullException('arrays');
if(arrays.length<2) throw new ArgumentException('arrays', 'Cannot compare a set of arrays less than 2.');
const first = arrays[0];
for(let i = 1, l = arrays.length; i<l; i++)
{
if(!areEqual(first, arrays[i], equalityComparison)) return false;
}
return true;
}
/**
* Compares two arrays for equality.
* @param {ArrayLike<T>} a
* @param {ArrayLike<T>} b
* @param {EqualityComparison<T>} equalityComparison
* @returns {boolean} True if both arrays have the same contents.
*/
export function areEqual<T> (
a: ArrayLike<T>,
b: ArrayLike<T>,
equalityComparison: EqualityComparison<T> = areEqualValue
): boolean
{
const len = validateSize(a, b);
if(type.isBoolean(len)) return len as boolean;
for(let i = 0; i<len; i++)
{
if(!equalityComparison(a[i], b[i])) return false;
}
return true;
}
function internalSort<T> (a: ArrayLike<T>, comparison: Comparison<T>): ArrayLike<T>
{
if(!a || a.length<2) return a;
const len = a.length;
let b: T[];
if(len>65536) b = new Array(len);
else
{
b = [];
b.length = len;
}
for(let i = 0; i<len; i++)
{
b[i] = a[i];
}
b.sort(comparison);
return b;
}
/**
* Returns true if both arrays contain the same contents regardless of order.
* @param {ArrayLike<T>} a
* @param {ArrayLike<T>} b
* @param {Comparison} comparison
* @returns {boolean}
*/
export function areEquivalent<T> (
a: ArrayLike<T>,
b: ArrayLike<T>,
comparison: Comparison<T> = compare): boolean
{
const len = validateSize(a, b);
if(type.isBoolean(len)) return len as boolean;
// There might be a better performing way to do this, but for the moment, this
// works quite well.
a = internalSort(a, comparison);
b = internalSort(b, comparison);
for(let i = 0; i<len; i++)
{
if(comparison(a[i], b[i])!==0) return false;
}
return true;
}