JavaScriptలో arraysతో పనిచేయడం అంటే ఇకపై మీరు for loop రాయాల్సిన అవసరం చాలా తక్కువ. ఈ భాష ఇప్పుడు మీ వద్ద ఉన్న క్లిష్టమైన, గందరగోళ డేటాను క్లీన్ మరియు చదవడానికి సులభంగా ఉండేలా మార్చే శక్తివంతమైన సాధనాలను అందిస్తుంది. ఈ గైడ్ బేసిక్స్ దాటిన తర్వాత వచ్చే అంశాలపై దృష్టి పెడుతుంది—అంటే flattening, reducing, querying మరియు మీ అసలు డేటాను మార్చకుండా ఉంచే కొత్త immutable patterns పై దృష్టి సారిస్తుంది.
flat() మరియు flatMap() ఉపయోగించి Nested Structuresలను Flatten చేయడం
రియల్-వరల్డ్ డేటాలో నెస్టెడ్ (nested) నిర్మాణాలు ఎక్కువగా ఉంటాయి. మీరు ఒక API నుండి రికార్డులను సేకరించినా, CSVని పార్స్ చేసినా లేదా ఒక కాన్ఫిగరేషన్ ఫైల్ను చదివినా, తరచుగా arrays లోపల arrays ఉండటం మీరు గమనిస్తారు. ఆ పొరలను (layers) ఒకే ఒక లీనియర్ లిస్ట్గా మార్చడానికి flat() ఉపయోగపడుతుంది.
ఒక nested array పై flat()ని ఉపయోగిస్తే, అది డిఫాల్ట్గా ఒక లెవల్ మాత్రమే flatten చేస్తుంది:
const nested = [[1, 2], [3, 4]];
const flat = nested.flat();
// [1, 2, 3, 4]
అసలు nested array ఏ విధంగా ఉందో అలాగే ఉంటుంది. ఒకవేళ మీ నెస్టెడ్ నిర్మాణం ఇంకా లోతుగా ఉంటే, flat(2) వంటి depth argumentని ఇవ్వండి లేదా ఎన్ని లేయర్లు ఉన్నాయో తెలియకపోతే flat(Infinity)ని ఉపయోగించండి. ఇది మాన్యువల్గా రికర్సివ్ హెల్పర్ ఫంక్షన్లను రాయడం కంటే చాలా సులభం.
మీరు ఎలిమెంట్స్ను ట్రాన్స్ఫార్మ్ చేయడంతో పాటు ఫలితాన్ని flatten చేయాలనుకున్నప్పుడు, flatMap() ఈ రెండింటినీ ఒకేసారి చేస్తుంది. ఇది ప్రతి ఎలిమెంట్ పై ఒక mapping functionని రన్ చేసి, ఆ తర్వాత వచ్చిన arraysని ఒక లెవల్ వరకు flatten చేస్తుంది. విడివిడిగా .map().flat() కాల్స్ చేయడం ద్వారా కూడా ఇది సాధ్యమే, కానీ flatMap() మధ్యంతర arrayని స్కిప్ చేస్తుంది, దీనివల్ల మెమరీ ఆదా అవుతుంది మరియు సెకండ్ ఇటరేషన్ అవసరం ఉండదు. వాక్యాల arrayని విడివిడి పదాలుగా మార్చడం దీనికి ఒక క్లాసిక్ ఉదాహరణ:
const lines = ['hello world', 'foo bar'];
const words = lines.flatMap(line => line.split(' '));
// ['hello', 'world', 'foo', 'bar']
Filtering మరియు Mapping: తేడాను తెలుసుకోండి
filter() అనేది మీ టెస్ట్ను పాస్ చేసుకున్న ఐటమ్స్తో మాత్రమే ఒక కొత్త 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ని రిటర్న్ చేస్తుంది. ప్రతి ఎలిమెంట్ను ట్రాన్స్ఫార్మ్ చేసి, కండిషనల్ చెక్ చేసినా, మీకు ప్రతి స్లాట్ కోసం true లేదా false కనిపిస్తుంది, ఎందుకంటే map() ఐటమ్స్ను ఎప్పుడూ తొలగించదు—అవి కేవలం మారుతుంది మాత్రమే. మరోవైపు, filter() మీ టెస్ట్ను పాస్ చేసుకున్న ఎలిమెంట్స్తో మాత్రమే తక్కువ పొడవు కలిగిన arrayని రిటర్న్ చేస్తుంది. మీరు డేటాను తొలగించాలనుకుంటే filter()ని వాడండి. డేటా కౌంట్ను అలాగే ఉంచుతూ ప్రతి డేటా పీస్ను ట్రాన్స్ఫార్మ్ చేయాలనుకుంటే map()ని ఉపయోగించండి.
reduce() ఉపయోగించి Arraysని Collapsing చేయడం
map() మరియు filter() arraysని రిటర్న్ చేసిన చోట, reduce() మొత్తం లిస్ట్ను ఒకే విలువగా మారుస్తుంది. ఇది ఎడమ నుండి కుడికి వెళ్తూ, ప్రతి దశలోనూ ఒక accumulatorని మోసుకెళ్తుంది.
const totals = [10, 20, 30];
const sum = totals.reduce((acc, current) => acc + current, 0);
// 60
పైన ఉన్న ఉదాహరణలో రెండవ argument—0—అంటే initial accumulator value. మీరు దీన్ని స్కిప్ చేస్తే, JavaScript మొదటి ఎలిమెంట్ను ప్రారంభ బిందువుగా తీసుకుని, ఇండెక్స్ 1 నుండి ఇటరేషన్ను ప్రారంభిస్తుంది. Array ఖాళీగా ఉన్నప్పుడు ఇది ఇబ్బంది కలిగించవచ్చు, ఎందుకంటే ఖాళీ arrayపై initial value లేకుండా reduce()ని కాల్ చేస్తే TypeError వస్తుంది.
Reduce అనేది కేవలం అరిథమెటిక్ (arithmetic) కోసం మాత్రమే కాదు. మీరు దీనిని ఫ్రీక్వెన్సీ టేబుల్స్ నిర్మించడానికి, ఆబ్జెక్ట్లను మెర్జ్ చేయడానికి, గరిష్ట విలువలను (maximum values) కనుగొనడానికి లేదా డేటాను బహుళ ట్రాన్స్ఫర్మేషన్ల ద్వారా పంపడానికి ఉపయోగించవచ్చు. ఇది చాలా ఫ్లెక్సిబుల్గా ఉంటుంది కాబట్టి, callbackను చిన్నదిగా ఉంచడం మరియు మీ వేరియబుల్స్కు స్పష్టమైన పేర్లు పెట్టడం మంచిది. ఒక క్లిష్టమైన reduce() బ్లాక్, అది రీప్లేస్ చేసిన లూప్ కంటే చదవడానికి కష్టంగా మారుతుంది.
Boolean Queries: every() మరియు some()
కొన్నిసార్లు మీకు కొత్త array అవసరం ఉండదు; కలెక్షన్కు సంబంధించి అవును లేదా కాదు (yes-or-no) అనే సమాధానం కావాలి. అన్ని ఎలిమెంట్స్ మీ కండిషన్ను సంతృప్తి పరిచినప్పుడు మాత్రమే every() trueని రిటర్న్ చేస్తుంది. మొదటి ఎలిమెంట్ విఫలమైతే, అది వెంటనే ఆగిపోయి falseని రిటర్న్ చేస్తుంది.
const scores = [85, 92, 78];
const allPassed = scores.every(s => s >= 50);
some() దీనికి విరుద్ధంగా పనిచేస్తుంది. కనీసం ఒక ఎలిమెంట్ టెస్ట్ను పాస్ చేసుకుంటే ఇది trueని రిటర్న్ చేస్తుంది. మ్యాచ్ దొరకగానే, ఇది అక్కడితో ఆగిపోతుంది.
const hasPerfectScore = scores.some(s => s === 100);
వాలిడేషన్ చెక్స్ కోసం ఈ మెథడ్స్ మాన్యువల్ లూప్స్ను రీప్లేస్ చేస్తాయి. ప్రతి ఫామ్ ఫీల్డ్ నింపబడిందో లేదో నిర్ధారించాలా? every()ని వాడండి. ఏదైనా యూజర్కు అడ్మిన్ హక్కులు ఉన్నాయో లేదో తెలుసుకోవాలా? some()ని వాడండి.
Mutation లేకుండా Inspect మరియు Update చేయడం
మోడరన్ JavaScript ఇమ్మ్యూటబిలిటీ (immutability) వైపు ఎక్కువగా మొగ్గు చూపుతుంది. ఈ మెథడ్స్ అసలు డేటాను తాకకుండానే arraysని ఇన్ స్పెక్ట్ చేయడానికి లేదా అప్డేట్ చేయడానికి మీకు సహాయపడతాయి.
keys() అనేది array యొక్క ఇండెక్స్లను కలిగి ఉన్న ఒక iterator ఆబ్జెక్ట్ను రిటర్న్ చేస్తుంది. entries() అనేది [index, value] జంటల (pairs) యొక్క iteratorని రిటర్న్ చేస్తుంది. మీరు క్లీన్ డీస్ట్రక్చరింగ్ (destructuring) చేయాలనుకున్నప్పుడు for...of లూప్స్లో ఇవి బాగా ఉపయోగపడతాయి:
const fruits = ['apple', 'banana'];
for (const [index, fruit] of fruits.entries()) {
console.log(index, fruit);
}
with() అనేది భాషకు కొత్తగా చేర్చబడిన ఫీచర్, ఇది ఒక నిర్దిష్ట ఇండెక్స్ వద్ద ఉన్న ఎలిమెంట్ను మారుస్తుంది మరియు ఒక కొత్త అర్రేను (array) తిరిగి ఇస్తుంది. ఇది బ్రాకెట్ అసైన్మెంట్—arr[index] = value—చేసే అవసరాలనే తీరుస్తుంది, కానీ ఇది మూల అర్రేను (source array) మార్చదు. React వంటి ఫ్రేమ్వర్క్లలో, డైరెక్ట్ మ్యుటేషన్ (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 సింటాక్స్ మరియు rest పారామీటర్ రెండింటికీ ఒకే మూడు చుక్కలు ఉంటాయి, కానీ అవి డేటాను వ్యతిరేక దిశలలో కదిలిస్తాయి.
ఒక అర్రేను విడివిడి ఎలిమెంట్స్గా విస్తరించడానికి spread operatorని ఉపయోగించండి. అర్రేలను విలీనం చేయడానికి (merge) లేదా క్లోన్ (clone) చేయడానికి ఇది అత్యంత సులభమైన మార్గం:
const front = [1, 2];
const back = [3, 4];
const merged = [...front, ...back];
const copy = [...merged];
మీరు సులభంగా అదనపు ఐటమ్స్ను కూడా చేర్చవచ్చు: [0, ...front, 99, ...back].
rest parameter బహుళ ఎలిమెంట్స్ను ఒకే అర్రేలోకి సేకరిస్తుంది. ఫంక్షన్ సిగ్నేచర్ (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 ఇన్పుట్ను స్వీకరించడం, దానిని అర్రేగా ప్రాసెస్ చేయడం, మరియు తిరిగి ఫంక్షన్ కాల్స్ లేదా కొత్త డేటా స్ట్రక్చర్లుగా పంపిణీ చేయడం వంటి సాధారణ పనులను నిర్వహిస్తాయి.
ముఖ్యమైన సారాంశం
ఈ మెథడ్స్ యొక్క లక్ష్యం వన్-లైనర్లతో టీమ్ సభ్యులను ఆకట్టుకోవడం కాదు. మీ ఉద్దేశ్యాన్ని స్పష్టంగా తెలియజేయడమే దీని లక్ష్యం. మరొక డెవలపర్ filter()ని చూసినప్పుడు, మీరు ఐటమ్స్ను తొలగిస్తున్నారని వారికి తెలుస్తుంది. వారు reduce()ని చూసినప్పుడు, మీరు డేటాను కుదించి (collapsing) ఒకే విలువగా మారుస్తున్నారని వారికి తెలుస్తుంది. వారు with()ని చూసినప్పుడు, అసలు అర్రే ఎక్కడో సురక్షితంగా ఉందని వారికి తెలుస్తుంది. ఈ టూల్స్లో ప్రావీణ్యం సంపాదించడం అంటే, స్వయంగా వివరణ ఇచ్చే కోడ్ను రాయడం అని అర్థం, ఇది ఎంతటి తెలివైన లూప్ (loop) కంటే కూడా ఎక్కువ సమయాన్ని ఆదా చేస్తుంది.
