JavaScript-இல் arrays உடன் பணியாற்றுவதற்கு இனி பெரும்பாலும் for loop எழுத வேண்டிய அவசியம் இல்லை. இந்த மொழி இப்போது சிக்கலான மற்றும் குழப்பமான தரவுகளை (data) சுத்தமான, எளிதில் வாசிக்கக்கூடிய மாற்றங்களாக மாற்றக்கூடிய வெளிப்படையான கருவிகளை வழங்குகிறது. இந்த வழிகாட்டி அடிப்படை விஷயங்களைத் தாண்டி—flattening, reducing, querying மற்றும் உங்கள் அசல் தரவை மாற்றாமல் பாதுகாக்கும் புதிய immutable patterns ஆகியவற்றில் கவனம் செலுத்துகிறது.

flat() மற்றும் flatMap() மூலம் ஒன்றினுள் ஒன்று இருக்கும் அமைப்புகளை (Nested Structures) தட்டையாக்குதல் (Flattening)

நிஜ உலகத் தரவுகள் பெரும்பாலும் ஒன்றினுள் ஒன்று அமைந்தே (nesting) இருக்கும். ஒரு API-லிருந்து பதிவுகளைப் பெற்றாலும், ஒரு CSV கோப்பைப் பகுப்பாய்வு செய்தாலும் அல்லது ஒரு configuration கோப்பைப் படித்தாலும், நீங்கள் பெரும்பாலும் arrays-க்குள் arrays இருப்பதைச் சந்திப்பீர்கள். அத்தகைய அடுக்குகளை ஒரு நேரியல் பட்டியலாக (linear list) சுருக்க flat() பயன்படுகிறது.

ஒரு nested array-இல் flat() ஐ அழைத்தால், அது இயல்பாக ஒரு அடுக்கு வரை மட்டுமே தட்டையாக்கும்:

const nested = [[1, 2], [3, 4]];
const flat = nested.flat();
// [1, 2, 3, 4]

அசல் nested array அப்படியே இருக்கும். உங்கள் அடுக்குகளின் ஆழம் அதிகமாக இருந்தால், flat(2) போன்ற ஆழத்தைக் குறிக்கும் வாதத்தை (depth argument) அல்லது எத்தனை அடுக்குகள் உள்ளன என்று தெரியாதபோது flat(Infinity) என்பதைக் கொடுக்கலாம். இது கைமுறையாக recursive helper functions எழுதுவதை விடச் சிறந்தது.

நீங்கள் உறுப்புகளை மாற்றியமைக்கவும் (transform) அதே நேரத்தில் அதன் முடிவை தட்டையாக மாற்றவும் விரும்பினால், flatMap() இரண்டையும் ஒரே முறையில் செய்கிறது. இது ஒவ்வொரு உறுப்பின் மீதும் ஒரு mapping function-ஐ இயக்கி, பின்னர் பெறப்பட்ட arrays-ஐ ஒரு அடுக்கு வரை தட்டையாக்கும். தனித்தனியாக .map().flat() என்று அழைப்பதன் மூலமும் இதைச் செய்யலாம், ஆனால் flatMap() இடைநிலை array-ஐத் தவிர்ப்பதால், இது நினைவகத்தைச் (memory) சேமிப்பதோடு இரண்டாவது சுழற்சியையும் (iteration) தவிர்க்கிறது. வாக்கியங்களின் array-ஐத் தனித்தனி வார்த்தைகளாகப் பிரிப்பது இதற்கு ஒரு சிறந்த உதாரணம்:

const lines = ['hello world', 'foo bar'];
const words = lines.flatMap(line => line.split(' '));
// ['hello', 'world', 'foo', 'bar']

Filtering மற்றும் Mapping: வித்தியாசத்தைப் புரிந்துகொள்ளுங்கள்

filter() உங்கள் சோதனையில் (test) தேர்ச்சி பெறும் உருப்படிகளை மட்டும் கொண்டு ஒரு புதிய array-ஐ உருவாக்குகிறது. அந்த உறுப்பைத் தக்கவைக்க callback ஒரு truthy மதிப்பையும், அதைத் தவிர்க்க ஒரு falsy மதிப்பையும் வழங்க வேண்டும். இது மூல array-ஐ ஒருபோதும் மாற்றாது (mutate).

const users = [
  { name: 'Ajay', active: true },
  { name: 'Bina', active: false }
];
const activeUsers = users.filter(u => u.active);

filter() மற்றும் map() ஆகிய இரண்டும் புதிய arrays-ஐத் தருவதாலும், callbacks-ஐ ஏற்றுக்கொள்வதாலும் அவற்றை எளிதில் குழப்பிக்கொள்ளலாம். ஆனால் அவற்றின் செயல்பாட்டில் வித்தியாசம் உள்ளது. map() அதே நீளம் கொண்ட (same length) ஒரு புதிய array-ஐத் தரும். ஒவ்வொரு உறுப்பையும் மாற்றியமைத்து, ஒரு நிபந்தனைச் சோதனையை (conditional check) மேற்கொண்டால், ஒவ்வொரு இடத்திலும் true அல்லது false என்பதைக் காண்பீர்கள்; ஏனெனில் map() உருப்படிகளைத் தவிர்க்காது—அவற்றை மாற்ற மட்டுமே செய்யும். மாறாக, filter() உங்கள் சோதனையில் தேர்ச்சி பெறும் உறுப்புகளை மட்டும் கொண்டு, குறுகிய நீளம் கொண்ட ஒரு array-ஐத் தரும். நீங்கள் தரவை நீக்க விரும்பினால், filter()-ஐப் பயன்படுத்தவும். தரவுகளின் எண்ணிக்கையைப் பராமரித்துக்கொண்டே அவற்றை மாற்றியமைக்க விரும்பினால், map()-ஐப் பயன்படுத்தவும்.

reduce() மூலம் arrays-ஐச் சுருக்குதல்

map() மற்றும் filter() ஆகியவை arrays-ஐத் தரும் நிலையில், reduce() ஒரு முழுப் பட்டியலையும் ஒரே ஒரு மதிப்பாகச் சுருக்குகிறது. இது இடமிருந்து வலமாகச் சென்று, ஒவ்வொரு படிநிலையிலும் ஒரு accumulator-ஐக் கொண்டு செல்கிறது.

const totals = [10, 20, 30];
const sum = totals.reduce((acc, current) => acc + current, 0);
// 60

மேலே உள்ள உதாரணத்தில் உள்ள இரண்டாவது வாதம் (0) என்பது ஆரம்பக்கட்ட accumulator மதிப்பு ஆகும். இதைத் தவிர்த்தால், JavaScript முதல் உறுப்பையே தொடக்கப் புள்ளியாக எடுத்துக்கொண்டு, index 1-லிருந்து சுழற்சியைத் தொடங்கும். array காலியாக இருக்கும்போது இது சிக்கலை ஏற்படுத்தும், ஏனெனில் ஒரு காலியான array-இல் ஆரம்ப மதிப்பு இல்லாமல் reduce()-ஐ அழைத்தால் TypeError ஏற்படும்.

Reduce என்பது கணக்கீடுகளுக்கு (arithmetic) மட்டுமல்ல. இதைப் பயன்படுத்தி frequency tables-களை உருவாக்கலாம், objects-களை இணைக்கலாம், அதிகபட்ச மதிப்புகளைக் கண்டறியலாம் அல்லது தரவுகளைப் பல மாற்றங்களுக்கு உட்படுத்தலாம். இது மிகவும் நெகிழ்வானது என்பதால், callback-ஐச் சிறியதாகவும், மாறிகளை (variables) தெளிவாகவும் பெயரிடுவது நல்லது. ஒரு சிக்கலான reduce() தொகுதியானது, அது மாற்றீடு செய்த loop-ஐ விட வாசிப்பதற்கு கடினமாக மாறிவிடும்.

Boolean Queries: every() மற்றும் some()

சில நேரங்களில் உங்களுக்கு ஒரு புதிய array தேவையில்லை; அந்தத் தொகுப்பைப் பற்றிய 'ஆம்' அல்லது 'இல்லை' என்ற பதில் மட்டுமே தேவைப்படும். every() என்பது அனைத்து உறுப்புகளும் உங்கள் நிபந்தனையைப் பூர்த்தி செய்தால் மட்டுமே true என்பதைத் தரும். முதல் உறுப்பு தோல்வியடைந்தால் கூட, அது உடனடியாக நின்று false என்பதைத் தரும்.

const scores = [85, 92, 78];
const allPassed = scores.every(s => s >= 50);

some() என்பது இதற்கு நேர்மாறானது. குறைந்தது ஒரு உறுப்பு சோதனையில் தேர்ச்சி பெற்றால் மட்டுமே இது true என்பதைத் தரும். ஒரு பொருத்தம் கிடைத்துவிட்டால், அது அங்கேயே நின்றுவிடும்.

const hasPerfectScore = scores.some(s => s === 100);

சரிபார்ப்புச் சோதனைகளுக்காக (validation checks) இவை கைமுறை loops-களுக்குப் பதிலாகப் பயன்படுகின்றன. ஒவ்வொரு படிவக் களமும் (form field) நிரப்பப்பட்டுள்ளதா என்பதை உறுதிப்படுத்த வேண்டுமா? every()-ஐப் பயன்படுத்தவும். ஏதேனும் ஒரு பயனருக்கு admin உரிமைகள் உள்ளனவா என்பதைத் தெரிந்துகொள்ள வேண்டுமா? some()-ஐப் பயன்படுத்தவும்.

மாற்றமின்றி (Without Mutation) ஆய்வு செய்தல் மற்றும் புதுப்பித்தல்

நவீன JavaScript, immutability (மாற்றமின்மை) முறையை அதிகம் சார்ந்துள்ளது. இந்த முறைகள் அசல் தரவைத் தொடாமல் array-களை ஆய்வு செய்ய அல்லது புதுப்பிக்க உதவுகின்றன.

keys() என்பது array-இன் index-களைக் கொண்ட ஒரு iterator object-ஐத் தரும். entries() என்பது [index, value] இணைகளைக் கொண்ட ஒரு iterator-ஐத் தரும். சுத்தமான destructuring செய்ய விரும்பும்போது for...of loops-களில் இவை சிறப்பாகச் செயல்படும்:

const fruits = ['apple', 'banana'];
for (const [index, fruit] of fruits.entries()) {
  console.log(index, fruit);
}

with() என்பது மொழியில் புதிதாக சேர்க்கப்பட்ட ஒரு வசதியாகும், இது ஒரு குறிப்பிட்ட index-இல் உள்ள உறுப்பை மாற்றிவிட்டு, ஒரு புதிய array-ஐத் திருப்பித் தரும். இது arr[index] = value போன்ற bracket assignment-ன் தேவையை நிறைவு செய்கிறது, ஆனால் மூல array-ஐ (source array) மாற்றாமல் அப்படியே விட்டுவிடும். React போன்ற frameworks-களில், நேரடி மாற்றம் (direct mutation) மாற்றங்களைக் கண்டறிதலை (change detection) பாதிக்கும் என்பதால், with() பாதுகாப்பான வழியாகும்:

const original = [10, 20, 30];
const updated = original.with(1, 99);
// original: [10, 20, 30]
// updated:  [10, 99, 30]

Spread மற்றும் Rest: ...-ன் இரு திசைகள்

Spread syntax மற்றும் rest parameter ஆகிய இரண்டும் ஒரே மூன்று புள்ளிகளைக் கொண்டிருந்தாலும், அவை தரவை எதிர் திசைகளில் நகர்த்துகின்றன.

ஒரு array-ஐ தனித்தனி உறுப்புகளாக விரிவுபடுத்த spread operator-ஐப் பயன்படுத்தவும். array-களை இணைக்க அல்லது அவற்றைப் பிரதி எடுக்க (clone) இதுவே மிகத் தெளிவான வழியாகும்:

const front = [1, 2];
const back = [3, 4];
const merged = [...front, ...back];

const copy = [...merged];

நீங்கள் கூடுதல் உறுப்புகளையும் எளிதாகச் சேர்க்கலாம்: [0, ...front, 99, ...back].

rest parameter பல உறுப்புகளை ஒரே array-க்குள் சேகரிக்கிறது. ஒரு function signature-க்குள், மீதமுள்ள அனைத்து arguments-களையும் இது சேகரிக்கும்:

function logFirst(first, ...rest) {
  console.log('First:', first);
  console.log('Rest:', rest);
}
logFirst('a', 'b', 'c');
// First: a
// Rest: ['b', 'c']

இவை இரண்டும் இணைந்து, மாறுபடும் உள்ளீடுகளை (variadic input) ஏற்றுக்கொள்வது, அவற்றை ஒரு array-ஆகச் செயலாக்குவது மற்றும் பின்னர் அவற்றை மீண்டும் function calls அல்லது புதிய தரவு அமைப்புகளாக (data structures) விரிவுபடுத்துவது போன்ற பொதுவான பணிகளைக் கையாளுகின்றன.

உண்மையான பயன்

இந்த முறைகளின் நோக்கம், ஒரு வரி குறியீடுகளால் (one-liners) சக ஊழியர்களைக் கவர வேண்டும் என்பதல்ல. மாறாக, உங்கள் நோக்கம் (intent) தெளிவாகத் தெரிவதே இதன் நோக்கமாகும். மற்றொரு டெவலப்பர் filter()-ஐப் பார்க்கும்போது, நீங்கள் உறுப்புகளை நீக்குகிறீர்கள் என்பதைத் தெரிந்து கொள்வார். reduce()-ஐப் பார்க்கும்போது, நீங்கள் தரவைச் சுருக்குகிறீர்கள் என்பதைத் தெரிந்து கொள்வார். with()-ஐப் பார்க்கும்போது, அசல் array எங்கோ அப்படியே பாதுகாப்பாக உள்ளது என்பதைத் தெரிந்து கொள்வார். இந்தத் கருவிகளில் தேர்ச்சி பெறுவது என்பது, தானாகவே விளங்கும் குறியீடுகளை எழுதுவதாகும்; இது எந்தவொரு புத்திசாலித்தனமான loop-ஐ விடவும் அதிக நேரத்தைச் சேமிக்கும்.