JavaScript ನಲ್ಲಿ ಅರೇಗಳೊಂದಿಗೆ (arrays) ಕೆಲಸ ಮಾಡುವುದು ಎಂದರೆ ಇನ್ನು ಮುಂದೆ ನೀವು for ಲೂಪ್ ಬರೆಯಬೇಕೆಂದಿಲ್ಲ. ಈ ಭಾಷೆಯು ಈಗ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಸುಲಭವಾಗಿ ಮತ್ತು ಸುಂದರವಾಗಿ ಪರಿವರ್ತಿಸಲು ಅಗತ್ಯವಾದ ಪರಿಣಾಮಕಾರಿ ಪರಿಕರಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಮಾರ್ಗದರ್ಶಿಯು ಮೂಲಭೂತ ಅಂಶಗಳ ನಂತರದ ವಿಷಯಗಳ ಮೇಲೆ ಗಮನ ಹರಿಸುತ್ತದೆ—flattening, reducing, querying ಮತ್ತು ನಿಮ್ಮ ಮೂಲ ಡೇಟಾವನ್ನು ಬದಲಿಸದ ಹೊಸ immutable patterns ಗಳ ಮೇಲೆ ಇದು ಕೇಂದ್ರೀಕರಿಸುತ್ತದೆ.
flat() ಮತ್ತು flatMap() ಬಳಸಿ ನೆಸ್ಟೆಡ್ (Nested) ರಚನೆಗಳನ್ನು ಫ್ಲಾಟನ್ (Flattening) ಮಾಡುವುದು
ನೈಜ ಪ್ರಪಂಚದ ಡೇಟಾವು ಹೆಚ್ಚಾಗಿ ನೆಸ್ಟೆಡ್ ಆಗಿರುತ್ತದೆ. ನೀವು API ನಿಂದ ರೆಕಾರ್ಡ್ಗಳನ್ನು ಪಡೆಯುವಾಗ, CSV ಅನ್ನು ಪಾರ್ಸ್ ಮಾಡುವಾಗ ಅಥವಾ ಕಾನ್ಫಿಗರೇಶನ್ ಫೈಲ್ ಅನ್ನು ಓದುವಾಗ, ಅರೇಗಳ ಒಳಗೆ ಅರೇಗಳಿರುವ (arrays inside arrays) ಸಂದರ್ಭ ಎದುರಾಗಬಹುದು. ಅಂತಹ ಪದರಗಳನ್ನು (layers) ಒಂದೇ ಸರಳ ಪಟ್ಟಿಯನ್ನಾಗಿ ಮಾಡಲು flat() ಬಳಕೆಯಾಗುತ್ತದೆ.
ನೆಸ್ಟೆಡ್ ಅರೇ ಮೇಲೆ flat() ಅನ್ನು ಬಳಸಿದಾಗ, ಅದು ಡಿಫಾಲ್ಟ್ ಆಗಿ ಒಂದು ಪದರವನ್ನು ಮಾತ್ರ ಫ್ಲಾಟನ್ ಮಾಡುತ್ತದೆ:
const nested = [[1, 2], [3, 4]];
const flat = nested.flat();
// [1, 2, 3, 4]
ಮೂಲ nested ಅರೇ ಹಾಗೆಯೇ ಇರುತ್ತದೆ. ನಿಮ್ಮ ನೆಸ್ಟಿಂಗ್ ಹೆಚ್ಚು ಪದರಗಳಿದ್ದರೆ, flat(2) ಅಥವಾ ಪದರಗಳ ಸಂಖ್ಯೆ ತಿಳಿಯದಿದ್ದಾಗ flat(Infinity) ನಂತಹ ಆರ್ಗ್ಯುಮೆಂಟ್ ಅನ್ನು ಬಳಸಿ. ಇದು ಮ್ಯಾನುಯಲ್ ಆಗಿ ರಿಸರ್ಸಿವ್ ಹೆಲ್ಪರ್ ಫಂಕ್ಷನ್ಗಳನ್ನು ಬರೆಯುವುದಕ್ಕಿಂತ ಉತ್ತಮವಾಗಿದೆ.
ನೀವು ಎಲಿಮೆಂಟ್ಗಳನ್ನು ಪರಿವರ್ತಿಸಬೇಕಾದಾಗ ಮತ್ತು ಅದರ ಫಲಿತಾಂಶವನ್ನು ಫ್ಲಾಟನ್ ಮಾಡಬೇಕಾದಾಗ, flatMap() ಈ ಎರಡನ್ನೂ ಒಂದೇ ಹಂತದಲ್ಲಿ ಮಾಡುತ್ತದೆ. ಇದು ಪ್ರತಿ ಎಲಿಮೆಂಟ್ ಮೇಲೆ ಮ್ಯಾಪಿಂಗ್ ಫಂಕ್ಷನ್ ಅನ್ನು ರನ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ನಂತರ ಬಂದ ಅರೇಗಳನ್ನು ಒಂದು ಪದರಕ್ಕೆ ಫ್ಲಾಟನ್ ಮಾಡುತ್ತದೆ. ಪ್ರತ್ಯೇಕವಾಗಿ .map().flat() ಬಳಸುವುದರಿಂದಲೂ ಇದು ಸಾಧ್ಯವಿದೆ, ಆದರೆ flatMap() ಮಧ್ಯಂತರ ಅರೇಯನ್ನು ಬಿಟ್ಟುಬಿಡುತ್ತದೆ, ಇದರಿಂದ ಮೆಮೊರಿ ಉಳಿತಾಯವಾಗುತ್ತದೆ ಮತ್ತು ಎರಡನೇ ಇಟರೇಶನ್ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ. ವಾಕ್ಯಗಳ ಅರೇಯನ್ನು ಪ್ರತ್ಯೇಕ ಪದಗಳಾಗಿ ವಿಂಗಡಿಸುವುದು ಇದರ ಒಂದು ಉದಾಹರಣೆ:
const lines = ['hello world', 'foo bar'];
const words = lines.flatMap(line => line.split(' '));
// ['hello', 'world', 'foo', 'bar']
Filtering ಮತ್ತು Mapping: ವ್ಯತ್ಯಾಸವನ್ನು ತಿಳಿಯಿರಿ
filter() ನಿಮ್ಮ ಪರೀಕ್ಷೆಯನ್ನು (test) ಪಾಸು ಮಾಡುವ ಐಟಂಗಳನ್ನು ಮಾತ್ರ ಒಳಗೊಂಡಿರುವ ಹೊಸ ಅರೇಯನ್ನು ರಚಿಸುತ್ತದೆ. ಎಲಿಮೆಂಟ್ ಅನ್ನು ಉಳಿಸಿಕೊಳ್ಳಲು ಕಾಲ್ಬ್ಯಾಕ್ (callback) ಟ್ರೂಥಿ (truthy) ಮೌಲ್ಯವನ್ನು ಅಥವಾ ಅದನ್ನು ಬಿಡಲು ಫಾಲ್ಸಿ (falsy) ಮೌಲ್ಯವನ್ನು ನೀಡಬೇಕು. ಇದು ಮೂಲ ಅರೇ ಅನ್ನು ಎಂದಿಗೂ ಬದಲಿಸುವುದಿಲ್ಲ (mutate).
const users = [
{ name: 'Ajay', active: true },
{ name: 'Bina', active: false }
];
const activeUsers = users.filter(u => u.active);
filter() ಮತ್ತು map() ಎರಡೂ ಹೊಸ ಅರೇಗಳನ್ನು ನೀಡುತ್ತವೆ ಮತ್ತು ಕಾಲ್ಬ್ಯಾಕ್ಗಳನ್ನು ಸ್ವೀಕರಿಸುತ್ತವೆ ಎಂಬ ಕಾರಣಕ್ಕೆ ಇವೆರಡರ ನಡುವೆ ಗೊಂದಲ ಉಂಟಾಗಬಹುದು. ಆದರೆ ಇವುಗಳ ನಡುವಿನ ವ್ಯತ್ಯಾಸವು ಅವುಗಳ ಕೆಲಸದಲ್ಲಿ (contract) ಇದೆ. map() ಯಾವಾಗಲೂ ಅದೇ ಉದ್ದದ (same length) ಹೊಸ ಅರೇಯನ್ನು ನೀಡುತ್ತದೆ. ನೀವು ಪ್ರತಿಯೊಂದು ಎಲಿಮೆಂಟ್ ಅನ್ನು ಪರಿವರ್ತಿಸಿದರೂ ಅಥವಾ ಕಂಡೀಷನಲ್ ಚೆಕ್ ಮಾಡಿದರೂ, ಪ್ರತಿಯೊಂದು ಸ್ಥಾನದಲ್ಲಿ true ಅಥವಾ false ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ, ಏಕೆಂದರೆ map() ಐಟಂಗಳನ್ನು ಎಂದಿಗೂ ಕೈಬಿಡುವುದಿಲ್ಲ—ಅದು ಕೇವಲ ಅವುಗಳನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ. ಇನ್ನೊಂದೆಡೆ, filter() ನಿಮ್ಮ ಪರೀಕ್ಷೆಯನ್ನು ಪಾಸು ಮಾಡುವ ಎಲಿಮೆಂಟ್ಗಳನ್ನು ಮಾತ್ರ ಒಳಗೊಂಡಿರುವ, ಅಲ್ಪ ಉದ್ದದ ಅರೇಯನ್ನು ನೀಡಬಹುದು. ನೀವು ಡೇಟಾವನ್ನು ತೆಗೆದುಹಾಕಲು ಬಯಸಿದರೆ, filter() ಬಳಸಿ. ನೀವು ಎಣಿಕೆಯನ್ನು (count) ಹಾಗೆಯೇ ಉಳಿಸಿಕೊಂಡು ಪ್ರತಿಯೊಂದು ಡೇಟಾವನ್ನು ಪರಿವರ್ತಿಸಲು ಬಯಸಿದರೆ, map() ಬಳಸಿ.
reduce() ಬಳಸಿ ಅರೇಗಳನ್ನು ಸಂಕ್ಷಿಪ್ತಗೊಳಿಸುವುದು (Collapsing)
map() ಮತ್ತು filter() ಅರೇಗಳನ್ನು ನೀಡಿದರೆ, reduce() ಇಡೀ ಪಟ್ಟಿಯನ್ನು ಒಂದೇ ಮೌಲ್ಯಕ್ಕೆ ತರುತ್ತದೆ. ಇದು ಎಡದಿಂದ ಬಲಕ್ಕೆ ಸಾಗುತ್ತದೆ ಮತ್ತು ಪ್ರತಿ ಹಂತದಲ್ಲಿ ಅಕ್ಯುಮ್ಯುಲೇಟರ್ (accumulator) ಅನ್ನು ಕೊಂಡೊಯ್ಯುತ್ತದೆ.
const totals = [10, 20, 30];
const sum = totals.reduce((acc, current) => acc + current, 0);
// 60
ಎರಡನೇ ಆರ್ಗ್ಯುಮೆಂಟ್—ಮೇಲಿನ ಉದಾಹರಣೆಯಲ್ಲಿರುವಂತೆ 0—ಇದು ಆರಂಭಿಕ ಅಕ್ಯುಮ್ಯುಲೇಟರ್ ಮೌಲ್ಯವಾಗಿದೆ. ಇದನ್ನು ಬಿಟ್ಟುಬಿಟ್ಟರೆ, JavaScript ಮೊದಲ ಎಲಿಮೆಂಟ್ ಅನ್ನು ಆರಂಭಿಕ ಬಿಂದುವನ್ನಾಗಿ ಬಳಸುತ್ತದೆ ಮತ್ತು ಇಂಡೆಕ್ಸ್ 1 ರಿಂದ ಇಟರೇಶನ್ ಪ್ರಾರಂಭಿಸುತ್ತದೆ. ಅರೇ ಖಾಲಿ ಇದ್ದಾಗ ಇದು ತೊಂದರೆ ನೀಡಬಹುದು, ಏಕೆಂದರೆ ಆರಂಭಿಕ ಮೌಲ್ಯವಿಲ್ಲದೆ ಖಾಲಿ ಅರೇ ಮೇಲೆ reduce() ಅನ್ನು ಕರೆಯುವುದು TypeError ಅನ್ನು ಉಂಟುಮಾಡುತ್ತದೆ.
Reduce ಕೇವಲ ಅಂಕಗಣಿತಕ್ಕೆ ಮಾತ್ರವಲ್ಲ. ನೀವು ಇದನ್ನು ಫ್ರೀಕ್ವೆನ್ಸಿ ಟೇಬಲ್ಗಳನ್ನು (frequency tables) ನಿರ್ಮಿಸಲು, ಆಬ್ಜೆಕ್ಟ್ಗಳನ್ನು ವಿಲೀನಗೊಳಿಸಲು (merge), ಗರಿಷ್ಠ ಮೌಲ್ಯಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲು ಅಥವಾ ಡೇಟಾವನ್ನು ಹಲವಾರು ಪರಿವರ್ತನೆಗಳ ಮೂಲಕ ಕಳುಹಿಸಲು ಬಳಸಬಹುದು. ಇದು ತುಂಬಾ ಫ್ಲೆಕ್ಸಿಬಲ್ ಆಗಿರುವುದರಿಂದ, ಕಾಲ್ಬ್ಯಾಕ್ ಅನ್ನು ಚಿಕ್ಕದಾಗಿ ಇಟ್ಟುಕೊಳ್ಳುವುದು ಮತ್ತು ನಿಮ್ಮ ವೇರಿಯೇಬಲ್ಗಳಿಗೆ ಸ್ಪಷ್ಟವಾದ ಹೆಸರು ನೀಡುವುದು ಉತ್ತಮ. ಒಂದು ದಟ್ಟವಾದ (dense) reduce() ಬ್ಲಾಕ್, ಅದು ಬದಲಿಸಿದ ಲೂಪ್ಗಿಂತಲೂ ಓದಲು ಕಷ್ಟವಾಗಬಹುದು.
ಬೂಲಿಯನ್ ಕ್ವೆರಿಗಳು (Boolean Queries): every() ಮತ್ತು some()
ಕೆಲವೊಮ್ಮೆ ನಿಮಗೆ ಹೊಸ ಅರೇಯ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ; ಬದಲಾಗಿ ಸಂಗ್ರಹದ (collection) ಬಗ್ಗೆ ಹೌದು ಅಥವಾ ಇಲ್ಲ ಎಂಬ ಉತ್ತರ ಬೇಕಾಗಿರುತ್ತದೆ. ಎಲ್ಲಾ ಎಲಿಮೆಂಟ್ಗಳು ನಿಮ್ಮ ಕಂಡೀಷನ್ ಅನ್ನು ಪೂರೈಸಿದರೆ ಮಾತ್ರ every() true ಅನ್ನು ನೀಡುತ್ತದೆ. ಮೊದಲ ಎಲಿಮೆಂಟ್ ವಿಫಲವಾದರೆ, ಅದು ತಕ್ಷಣವೇ ನಿಂತು false ಅನ್ನು ನೀಡುತ್ತದೆ.
const scores = [85, 92, 78];
const allPassed = scores.every(s => s >= 50);
some() ಇದರ ವಿರುದ್ಧವಾಗಿದೆ. ಕನಿಷ್ಠ ಒಂದು ಎಲಿಮೆಂಟ್ ಪರೀಕ್ಷೆಯನ್ನು ಪಾಸು ಮಾಡಿದರೆ ಇದು true ಅನ್ನು ನೀಡುತ್ತದೆ. ಹೊಂದಾಣಿಕೆಯಾದ ತಕ್ಷಣ ಇದು ಕೆಲಸವನ್ನು ನಿಲ್ಲಿಸುತ್ತದೆ (short-circuits).
const hasPerfectScore = scores.some(s => s === 100);
ವ್ಯಾಲಿಡೇಶನ್ ಚೆಕ್ಗಳಿಗಾಗಿ ಈ ವಿಧಾನಗಳು ಮ್ಯಾನುಯಲ್ ಲೂಪ್ಗಳ ಬದಲಿಗೆ ಬಳಕೆಯಾಗುತ್ತವೆ. ಪ್ರತಿಯೊಂದು ಫಾರ್ಮ್ ಫೀಲ್ಡ್ ಅನ್ನು ಭರ್ತಿ ಮಾಡಲಾಗಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಬೇಕೆ? every() ಬಳಸಿ. ಯಾವುದಾದರೂ ಬಳಕೆದಾರರಿಗೆ ಅಡ್ಮಿನ್ ಹಕ್ಕುಗಳಿವೆಯೇ ಎಂದು ತಿಳಿಯಬೇಕೆ? some() ಬಳಸಿ.
ಮ್ಯುಟೇಶನ್ (Mutation) ಇಲ್ಲದೆ ಇನ್ಸ್ಪೆಕ್ಟ್ ಮತ್ತು ಅಪ್ಡೇಟ್ ಮಾಡುವುದು
ಆಧುನಿಕ JavaScript ಇಮ್ಯುಟಬಿಲಿಟಿ (immutability) ಕಡೆಗೆ ಹೆಚ್ಚು ಒಲವು ಹೊಂದಿದೆ. ಈ ವಿಧಾನಗಳು ಮೂಲ ಅರೇಯನ್ನು ಮುಟ್ಟದೆ ಅದನ್ನು ಇನ್ಸ್ಪೆಕ್ಟ್ ಮಾಡಲು ಅಥವಾ ಅಪ್ಡೇಟ್ ಮಾಡಲು ಸಹಾಯ ಮಾಡುತ್ತವೆ.
keys() ಅರೇಯ ಇಂಡೆಸ್ಗಳನ್ನು ಒಳಗೊಂಡಿರುವ ಇಟರೇಟರ್ (iterator) ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ನೀಡುತ್ತದೆ. entries() [index, value] ಜೋಡಿಗಳ ಇಟರೇಟರ್ ಅನ್ನು ನೀಡುತ್ತದೆ. ನೀವು ಕ್ಲೀನ್ ಡೆಸ್ಟ್ರಕ್ಚರಿಂಗ್ (destructuring) ಬಯಸಿದಾಗ for...of ಲೂಪ್ಗಳಲ್ಲಿ ಇವು ಹೆಚ್ಚು ಉಪಯುಕ್ತವಾಗಿವೆ:
const fruits = ['apple', 'banana'];
for (const [index, fruit] of fruits.entries()) {
console.log(index, fruit);
}
with() ಎಂಬುದು ಭಾಷೆಗೆ ಸೇರ್ಪಡೆಯಾದ ಹೊಸ ವಿಧಾನವಾಗಿದ್ದು, ಇದು ನಿರ್ದಿಷ್ಟ ಇಂಡೆಕ್ಸ್ನಲ್ಲಿರುವ ಅಂಶವನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ ಮತ್ತು ಸಂಪೂರ್ಣವಾಗಿ ಹೊಸ ಅರೇಯನ್ನು ನೀಡುತ್ತದೆ. ಇದು ಬ್ರ್ಯಾಕೆಟ್ ಅಸೈನ್ಮೆಂಟ್—arr[index] = value—ಅದರಂತೆಯೇ ಕೆಲಸ ಮಾಡುತ್ತದೆ, ಆದರೆ ಮೂಲ ಅರೇಯನ್ನು ಬದಲಾಯಿಸದೆ ಹಾಗೆಯೇ ಇರಿಸುತ್ತದೆ. React ನಂತಹ ಫ್ರೇಮ್ವರ್ಕ್ಗಳಲ್ಲಿ, ನೇರ ಬದಲಾವಣೆಗಳು (direct mutation) ಚೇಂಜ್ ಡಿಟೆಕ್ಷನ್ ಪ್ರಕ್ರಿಯೆಯನ್ನು ಹಾಳುಮಾಡುತ್ತವೆ, ಅಂತಹ ಸಂದರ್ಭಗಳಲ್ಲಿ with() ಹೆಚ್ಚು ಸುರಕ್ಷಿತವಾದ ಮಾರ್ಗವಾಗಿದೆ:
const original = [10, 20, 30];
const updated = original.with(1, 99);
// original: [10, 20, 30]
// updated: [10, 99, 30]
Spread ಮತ್ತು Rest: ... ನ ಎರಡು ದಿಕ್ಕುಗಳು
Spread ಸಿಂಟ್ಯಾಕ್ಸ್ ಮತ್ತು rest ಪ್ಯಾರಾಮೀಟರ್ ಎರಡೂ ಒಂದೇ ರೀತಿಯ ಮೂರು ಚುಕ್ಕೆಗಳನ್ನು ಬಳಸುತ್ತವೆ, ಆದರೆ ಅವು ಡೇಟಾವನ್ನು ವಿರುದ್ಧ ದಿಕ್ಕುಗಳಲ್ಲಿ ಚಲಾಯಿಸುತ್ತವೆ.
ಅರೇಯನ್ನು ಪ್ರತ್ಯೇಕ ಅಂಶಗಳಾಗಿ ವಿಸ್ತರಿಸಲು spread operator ಅನ್ನು ಬಳಸಿ. ಅರೇಗಳನ್ನು ವಿಲೀನಗೊಳಿಸಲು ಅಥವಾ ಅವುಗಳನ್ನು ಕ್ಲೋನ್ ಮಾಡಲು ಇದು ಅತ್ಯಂತ ಸುಲಭವಾದ ಮಾರ್ಗವಾಗಿದೆ:
const front = [1, 2];
const back = [3, 4];
const merged = [...front, ...back];
const copy = [...merged];
ನೀವು ಸುಲಭವಾಗಿ ಹೆಚ್ಚುವರಿ ಅಂಶಗಳನ್ನು ಸೇರಿಸಬಹುದು: [0, ...front, 99, ...back].
rest parameter ಅನೇಕ ಅಂಶಗಳನ್ನು ಒಂದೇ ಅರೇಯಾಗಿ ಸಂಗ್ರಹಿಸುತ್ತದೆ. ಫಂಕ್ಷನ್ ಸಿಗ್ನೇಚರ್ನ ಒಳಗಡೆ, ಬಾಕಿ ಉಳಿದಿರುವ ಯಾವುದೇ ಆರ್ಗ್ಯುಮೆಂಟ್ಗಳನ್ನು ಇದು ಸಂಗ್ರಹಿಸುತ್ತದೆ:
function logFirst(first, ...rest) {
console.log('First:', first);
console.log('Rest:', rest);
}
logFirst('a', 'b', 'c');
// First: a
// Rest: ['b', 'c']
ಇವೆರಡೂ ಒಟ್ಟಾಗಿ ವೈರಿಯಾಡಿಕ್ ಇನ್ಪುಟ್ (variadic input) ಸ್ವೀಕರಿಸುವುದು, ಅದನ್ನು ಅರೇಯಾಗಿ ಪ್ರೊಸೆಸ್ ಮಾಡುವುದು ಮತ್ತು ನಂತರ ಫಂಕ್ಷನ್ ಕರೆಗಳು ಅಥವಾ ಹೊಸ ಡೇಟಾ ಸ್ಟ್ರಕ್ಚರ್ಗಳಿಗೆ ವಿಸ್ತರಿಸುವ ಸಾಮಾನ್ಯ ಕೆಲಸವನ್ನು ನಿರ್ವಹಿಸುತ್ತವೆ.
ನಿಜವಾದ ಸಾರಾಂಶ
ಈ ವಿಧಾನಗಳ ಉದ್ದೇಶ ಒನ್-ಲೈನರ್ಗಳ ಮೂಲಕ ಸಹೋದ್ಯೋಗಿಗಳನ್ನು ಮೆಚ್ಚಿಸುವುದಲ್ಲ. ಬದಲಾಗಿ ನಿಮ್ಮ ಉದ್ದೇಶವನ್ನು ಸ್ಪಷ್ಟಪಡಿಸುವುದು ಇದರ ಗುರಿಯಾಗಿದೆ. ಇನ್ನೊಬ್ಬ ಡೆವಲಪರ್ filter() ಅನ್ನು ನೋಡಿದಾಗ, ನೀವು ಅಂಶಗಳನ್ನು ತೆಗೆದುಹಾಕುತ್ತಿದ್ದೀರಿ ಎಂದು ಅವರಿಗೆ ತಿಳಿಯುತ್ತದೆ. ಅವರು reduce() ಅನ್ನು ನೋಡಿದಾಗ, ನೀವು ಡೇಟಾವನ್ನು ಸಂಕ್ಷೇಪಿಸುತ್ತಿದ್ದೀರಿ ಎಂದು ತಿಳಿಯುತ್ತದೆ. ಅವರು with() ಅನ್ನು ನೋಡಿದಾಗ, ಮೂಲ ಅರೇ ಎಲ್ಲೋ ಅಕ್ಷತವಾಗಿದೆ ಎಂದು ಅವರಿಗೆ ತಿಳಿಯುತ್ತದೆ. ಈ ಪರಿಕರಗಳಲ್ಲಿ ಪರಿಣತಿ ಪಡೆಯುವುದು ಎಂದರೆ ಸ್ವಯಂ ವಿವರಣಾತ್ಮಕ ಕೋಡ್ ಬರೆಯುವುದು ಎಂದರ್ಥ, ಮತ್ತು ಇದು ಯಾವುದೇ ಚತುರ ಲೂಪ್ (clever loop) ಗಿಂತ ಹೆಚ್ಚಿನ ಸಮಯವನ್ನು ಉಳಿಸುತ್ತದೆ.
