Skip to content

Commit 5a1d9d9

Browse files
authored
Create UniqueArrayEn.js
1 parent 5faac80 commit 5a1d9d9

File tree

1 file changed

+339
-0
lines changed

1 file changed

+339
-0
lines changed

unique/UniqueArrayEn.js

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
/**
2+
* Comprehensive Array Deduplication Class
3+
* Demonstrates 18 different methods for array deduplication in JavaScript
4+
* Each method showcases different optimization strategies and ECMAScript features
5+
*/
6+
class UniqueArray {
7+
constructor(arr) {
8+
this.originalArray = arr; // Preserve original array immutability
9+
}
10+
11+
// Method 1: Double Nested Loop
12+
methodDoubleLoop() {
13+
console.time("DoubleLoop");
14+
const arr = this.originalArray.slice();
15+
const uniqueArr = [];
16+
17+
// O(n²) time complexity - brute force comparison
18+
for (let i = 0; i < arr.length; i++) {
19+
let isUnique = true;
20+
for (let j = 0; j < uniqueArr.length; j++) {
21+
if (arr[i] === uniqueArr[j]) {
22+
isUnique = false;
23+
break;
24+
}
25+
}
26+
if (isUnique) uniqueArr.push(arr[i]);
27+
}
28+
29+
console.log("Double Loop:", uniqueArr);
30+
console.timeEnd("DoubleLoop");
31+
}
32+
33+
// Method 2: indexOf Check
34+
methodIndexOfCheck() {
35+
console.time("IndexOfCheck");
36+
const arr = this.originalArray.slice();
37+
const uniqueArr = [];
38+
39+
// Leverage built-in indexOf for existence check
40+
arr.forEach(item => {
41+
if (uniqueArr.indexOf(item) === -1) {
42+
uniqueArr.push(item);
43+
}
44+
});
45+
46+
console.log("indexOf Check:", uniqueArr);
47+
console.timeEnd("IndexOfCheck");
48+
}
49+
50+
// Method 3: includes Check
51+
methodIncludesCheck() {
52+
console.time("IncludesCheck");
53+
const arr = this.originalArray.slice();
54+
const uniqueArr = [];
55+
56+
// Modern alternative to indexOf with better readability
57+
arr.forEach(item => {
58+
if (!uniqueArr.includes(item)) {
59+
uniqueArr.push(item);
60+
}
61+
});
62+
63+
console.log("Includes Check:", uniqueArr);
64+
console.timeEnd("IncludesCheck");
65+
}
66+
67+
// Method 4: Reverse Splice (Right to Left)
68+
methodReverseSplice() {
69+
console.time("ReverseSplice");
70+
const arr = this.originalArray.slice();
71+
let length = arr.length;
72+
73+
// Modify array in-place from end to start
74+
while (length--) {
75+
for (let i = 0; i < length; i++) {
76+
if (arr[length] === arr[i]) {
77+
arr.splice(length, 1);
78+
break;
79+
}
80+
}
81+
}
82+
83+
console.log("Reverse Splice:", arr);
84+
console.timeEnd("ReverseSplice");
85+
}
86+
87+
// Method 5: Nested Reverse Splice
88+
methodNestedReverseSplice() {
89+
console.time("NestedReverseSplice");
90+
const arr = this.originalArray.slice();
91+
let length = arr.length;
92+
93+
// Optimized reverse comparison with nested while loops
94+
while (length--) {
95+
let i = length;
96+
while (i--) {
97+
if (arr[length] === arr[i]) {
98+
arr.splice(length, 1);
99+
break;
100+
}
101+
}
102+
}
103+
104+
console.log("Nested Reverse Splice:", arr);
105+
console.timeEnd("NestedReverseSplice");
106+
}
107+
108+
// Method 6: Forward Splice
109+
methodForwardSplice() {
110+
console.time("ForwardSplice");
111+
const arr = this.originalArray.slice();
112+
let length = arr.length;
113+
114+
// In-place modification from start to end
115+
for (let i = 0; i < length; i++) {
116+
for (let j = i + 1; j < length; j++) {
117+
if (arr[i] === arr[j]) {
118+
arr.splice(j, 1);
119+
length--;
120+
j--;
121+
}
122+
}
123+
}
124+
125+
console.log("Forward Splice:", arr);
126+
console.timeEnd("ForwardSplice");
127+
}
128+
129+
// Method 7: indexOf Position Check
130+
methodIndexPosition() {
131+
console.time("IndexPosition");
132+
const arr = this.originalArray.slice();
133+
const uniqueArr = [];
134+
135+
// Compare current index with first occurrence index
136+
arr.forEach((item, index) => {
137+
if (arr.indexOf(item) === index) {
138+
uniqueArr.push(item);
139+
}
140+
});
141+
142+
console.log("Index Position:", uniqueArr);
143+
console.timeEnd("IndexPosition");
144+
}
145+
146+
// Method 8: Filter with indexOf
147+
methodFilterIndex() {
148+
console.time("FilterIndex");
149+
const arr = this.originalArray.slice();
150+
151+
// Concise functional programming approach
152+
const result = arr.filter((item, index) => arr.indexOf(item) === index);
153+
154+
console.log("Filter + indexOf:", result);
155+
console.timeEnd("FilterIndex");
156+
}
157+
158+
// Method 9: Object Property Map
159+
methodObjectMap() {
160+
console.time("ObjectMap");
161+
const arr = this.originalArray.slice();
162+
const objMap = {};
163+
164+
// Using object properties for uniqueness check
165+
arr.forEach(item => objMap[item] = true);
166+
const result = Object.keys(objMap).map(Number);
167+
168+
console.log("Object Map:", result);
169+
console.timeEnd("ObjectMap");
170+
}
171+
172+
// Method 10: ES6 Map
173+
methodES6Map() {
174+
console.time("ES6Map");
175+
const arr = this.originalArray.slice();
176+
const map = new Map();
177+
178+
// Preserve insertion order with Map
179+
arr.forEach(item => map.set(item, true));
180+
const result = Array.from(map.keys());
181+
182+
console.log("ES6 Map:", result);
183+
console.timeEnd("ES6Map");
184+
}
185+
186+
// Method 11: Set Conversion
187+
methodSetConversion() {
188+
console.time("SetConversion");
189+
// Most modern and efficient method
190+
const result = [...new Set(this.originalArray)];
191+
192+
console.log("Set Conversion:", result);
193+
console.timeEnd("SetConversion");
194+
}
195+
196+
// Method 12: Sort and Adjacent Check
197+
methodSortAdjacent() {
198+
console.time("SortAdjacent");
199+
const arr = this.originalArray.slice();
200+
201+
// Sort-based approach modifies original order
202+
arr.sort();
203+
for (let i = arr.length - 1; i > 0; i--) {
204+
if (arr[i] === arr[i - 1]) {
205+
arr.splice(i, 1);
206+
}
207+
}
208+
209+
console.log("Sort + Adjacent:", arr);
210+
console.timeEnd("SortAdjacent");
211+
}
212+
213+
// Method 13: Custom Sort and Clean
214+
methodCustomSort() {
215+
console.time("CustomSort");
216+
const arr = this.originalArray.slice();
217+
218+
// Custom sorting logic for type consistency
219+
arr.sort((a, b) => a.toString().localeCompare(b.toString()));
220+
for (let i = 0; i < arr.length - 1; i++) {
221+
if (arr[i] === arr[i + 1]) {
222+
arr.splice(i, 1);
223+
i--;
224+
}
225+
}
226+
227+
console.log("Custom Sort:", arr);
228+
console.timeEnd("CustomSort");
229+
}
230+
231+
// Method 14: Reduce Accumulator
232+
methodReduceAccumulator() {
233+
console.time("ReduceAccumulator");
234+
const arr = this.originalArray.slice();
235+
236+
// Functional approach with reducer
237+
const result = arr.reduce((acc, item) => {
238+
return acc.includes(item) ? acc : [...acc, item];
239+
}, []);
240+
241+
console.log("Reduce Accumulator:", result);
242+
console.timeEnd("ReduceAccumulator");
243+
}
244+
245+
// Method 15: Optimized Push
246+
methodOptimizedPush() {
247+
console.time("OptimizedPush");
248+
const arr = this.originalArray.slice();
249+
const uniqueArr = [];
250+
251+
// Optimized version of indexOf check
252+
arr.forEach(item => {
253+
uniqueArr.indexOf(item) === -1 && uniqueArr.push(item);
254+
});
255+
256+
console.log("Optimized Push:", uniqueArr);
257+
console.timeEnd("OptimizedPush");
258+
}
259+
260+
// Method 16: Type-safe Filter
261+
methodTypeSafeFilter() {
262+
console.time("TypeSafeFilter");
263+
const arr = this.originalArray.slice();
264+
const seen = {};
265+
266+
// Prevent type coercion issues
267+
const result = arr.filter(item => {
268+
const key = typeof item + JSON.stringify(item);
269+
return seen[key] ? false : (seen[key] = true);
270+
});
271+
272+
console.log("Type-safe Filter:", result);
273+
console.timeEnd("TypeSafeFilter");
274+
}
275+
276+
// Method 17: Recursive Approach
277+
methodRecursiveDedupe(arr = this.originalArray.slice()) {
278+
console.time("RecursiveDedupe");
279+
// Base case for recursion
280+
if (arr.length <= 1) return arr;
281+
282+
const [first, ...rest] = arr;
283+
const filtered = rest.filter(item => item !== first);
284+
285+
// Recursively process remaining elements
286+
const result = [first, ...this.methodRecursiveDedupe(filtered)];
287+
288+
console.timeEnd("RecursiveDedupe");
289+
return result;
290+
}
291+
292+
// Method 18: Hash Table Optimization
293+
methodHashTable() {
294+
console.time("HashTable");
295+
const arr = this.originalArray.slice();
296+
const hash = {};
297+
const result = [];
298+
299+
// Optimal O(n) time complexity solution
300+
for (let item of arr) {
301+
const key = typeof item + JSON.stringify(item);
302+
if (!hash[key]) {
303+
hash[key] = true;
304+
result.push(item);
305+
}
306+
}
307+
308+
console.log("Hash Table:", result);
309+
console.timeEnd("HashTable");
310+
}
311+
}
312+
313+
// Test Execution
314+
(() => {
315+
const testArray = [1, 1, 3, -1, 1, 2, 2, 4, 2, 2, -1];
316+
const deduplicator = new UniqueArray(testArray);
317+
318+
console.log("=== Array Deduplication Benchmark ===");
319+
320+
// Execute all methods
321+
deduplicator.methodDoubleLoop();
322+
deduplicator.methodIndexOfCheck();
323+
deduplicator.methodIncludesCheck();
324+
deduplicator.methodReverseSplice();
325+
deduplicator.methodNestedReverseSplice();
326+
deduplicator.methodForwardSplice();
327+
deduplicator.methodIndexPosition();
328+
deduplicator.methodFilterIndex();
329+
deduplicator.methodObjectMap();
330+
deduplicator.methodES6Map();
331+
deduplicator.methodSetConversion();
332+
deduplicator.methodSortAdjacent();
333+
deduplicator.methodCustomSort();
334+
deduplicator.methodReduceAccumulator();
335+
deduplicator.methodOptimizedPush();
336+
deduplicator.methodTypeSafeFilter();
337+
console.log("Recursive:", deduplicator.methodRecursiveDedupe());
338+
deduplicator.methodHashTable();
339+
})();

0 commit comments

Comments
 (0)