[{"data":1,"prerenderedAt":1375},["ShallowReactive",2],{"blog-\u002Fblog\u002Fjavascript-array-searching-sorting":3},{"id":4,"title":5,"body":6,"description":1360,"difficulty":1361,"extension":1362,"framework":1363,"frameworkSlug":1364,"meta":1365,"navigation":789,"order":134,"path":1366,"qaPath":1367,"seo":1368,"stem":1369,"subtopic":1370,"topic":1371,"topicSlug":1372,"updated":1373,"__hash__":1374},"blog\u002Fblog\u002Fjavascript-array-searching-sorting.md","JavaScript Array Searching & Sorting — indexOf, find, the sort() Gotcha and Comparators",{"type":7,"value":8,"toc":1347},"minimark",[9,14,27,31,60,183,204,208,241,288,303,307,321,420,443,447,457,545,551,555,575,637,657,692,696,709,869,875,879,893,963,970,1042,1046,1059,1161,1175,1179,1197,1247,1257,1261,1340,1343],[10,11,13],"h2",{"id":12},"finding-and-ordering-data","Finding and ordering data",[15,16,17,18,22,23,26],"p",{},"Two of the most common things you do with arrays are ",[19,20,21],"strong",{},"find an element"," and ",[19,24,25],{},"put elements\nin order",". JavaScript provides several searching methods with subtly different behavior, and\na sorting method with one of the language's most infamous gotchas. Getting these right — and\nknowing the traps — is everyday-essential and a frequent interview topic. This guide covers\nhow to search effectively and how to sort correctly, including objects and multi-key cases.",[10,28,30],{"id":29},"searching-by-value-indexof-lastindexof-includes","Searching by value: indexOf, lastIndexOf, includes",[15,32,33,39,40,43,44,47,48,53,54,59],{},[19,34,35],{},[36,37,38],"code",{},"indexOf"," returns the index of the first strictly-equal (",[36,41,42],{},"===",") element, or ",[36,45,46],{},"-1"," if\nabsent. ",[19,49,50],{},[36,51,52],{},"lastIndexOf"," does the same from the end. ",[19,55,56],{},[36,57,58],{},"includes"," returns a boolean.",[61,62,67],"pre",{"className":63,"code":64,"language":65,"meta":66,"style":66},"language-js shiki shiki-themes github-light github-dark","const a = ['x', 'y', 'z', 'y']\na.indexOf('y')      \u002F\u002F 1\na.lastIndexOf('y')  \u002F\u002F 3\na.includes('y')     \u002F\u002F true when you just need yes\u002Fno\na.indexOf('q')      \u002F\u002F -1 (not found)\n","js","",[36,68,69,111,132,149,166],{"__ignoreMap":66},[70,71,74,78,82,85,89,93,96,99,101,104,106,108],"span",{"class":72,"line":73},"line",1,[70,75,77],{"class":76},"szBVR","const",[70,79,81],{"class":80},"sj4cs"," a",[70,83,84],{"class":76}," =",[70,86,88],{"class":87},"sVt8B"," [",[70,90,92],{"class":91},"sZZnC","'x'",[70,94,95],{"class":87},", ",[70,97,98],{"class":91},"'y'",[70,100,95],{"class":87},[70,102,103],{"class":91},"'z'",[70,105,95],{"class":87},[70,107,98],{"class":91},[70,109,110],{"class":87},"]\n",[70,112,114,117,120,123,125,128],{"class":72,"line":113},2,[70,115,116],{"class":87},"a.",[70,118,38],{"class":119},"sScJk",[70,121,122],{"class":87},"(",[70,124,98],{"class":91},[70,126,127],{"class":87},")      ",[70,129,131],{"class":130},"sJ8bj","\u002F\u002F 1\n",[70,133,135,137,139,141,143,146],{"class":72,"line":134},3,[70,136,116],{"class":87},[70,138,52],{"class":119},[70,140,122],{"class":87},[70,142,98],{"class":91},[70,144,145],{"class":87},")  ",[70,147,148],{"class":130},"\u002F\u002F 3\n",[70,150,152,154,156,158,160,163],{"class":72,"line":151},4,[70,153,116],{"class":87},[70,155,58],{"class":119},[70,157,122],{"class":87},[70,159,98],{"class":91},[70,161,162],{"class":87},")     ",[70,164,165],{"class":130},"\u002F\u002F true when you just need yes\u002Fno\n",[70,167,169,171,173,175,178,180],{"class":72,"line":168},5,[70,170,116],{"class":87},[70,172,38],{"class":119},[70,174,122],{"class":87},[70,176,177],{"class":91},"'q'",[70,179,127],{"class":87},[70,181,182],{"class":130},"\u002F\u002F -1 (not found)\n",[15,184,185,186,188,189,192,193,196,197,200,201,203],{},"A classic bug is treating the ",[36,187,46],{}," result as falsy: ",[36,190,191],{},"if (a.indexOf(x))"," is wrong because\nindex ",[36,194,195],{},"0"," is also falsy. Compare with ",[36,198,199],{},"!== -1",", or use ",[36,202,58],{}," when you only need a\nboolean.",[10,205,207],{"id":206},"the-nan-gotcha","The NaN gotcha",[15,209,210,212,213,215,216,219,220,223,224,226,227,230,231,233,234,237,238,240],{},[36,211,38],{}," uses ",[36,214,42],{},", and ",[36,217,218],{},"NaN === NaN"," is ",[19,221,222],{},"false"," — so ",[36,225,38],{}," can never find ",[36,228,229],{},"NaN",".\n",[36,232,58],{}," uses the ",[19,235,236],{},"SameValueZero"," algorithm, which treats ",[36,239,229],{}," as equal to itself.",[61,242,244],{"className":63,"code":243,"language":65,"meta":66,"style":66},"[NaN].indexOf(NaN)    \u002F\u002F -1 can't find it\n[NaN].includes(NaN)   \u002F\u002F true\n",[36,245,246,268],{"__ignoreMap":66},[70,247,248,251,253,256,258,260,262,265],{"class":72,"line":73},[70,249,250],{"class":87},"[",[70,252,229],{"class":80},[70,254,255],{"class":87},"].",[70,257,38],{"class":119},[70,259,122],{"class":87},[70,261,229],{"class":80},[70,263,264],{"class":87},")    ",[70,266,267],{"class":130},"\u002F\u002F -1 can't find it\n",[70,269,270,272,274,276,278,280,282,285],{"class":72,"line":113},[70,271,250],{"class":87},[70,273,229],{"class":80},[70,275,255],{"class":87},[70,277,58],{"class":119},[70,279,122],{"class":87},[70,281,229],{"class":80},[70,283,284],{"class":87},")   ",[70,286,287],{"class":130},"\u002F\u002F true\n",[15,289,290,291,295,296,298,299,302],{},"If you need the ",[292,293,294],"em",{},"index"," of a ",[36,297,229],{},", use ",[36,300,301],{},"findIndex(Number.isNaN)",". This difference is a\nfavorite interview question because it reveals whether you know how equality works under each\nmethod.",[10,304,306],{"id":305},"searching-by-predicate-find-findindex","Searching by predicate: find, findIndex",[15,308,309,310,22,315,320],{},"When you're searching for \"the element where some condition holds\" (especially objects),\n",[19,311,312],{},[36,313,314],{},"find",[19,316,317],{},[36,318,319],{},"findIndex"," take a predicate function rather than a value.",[61,322,324],{"className":63,"code":323,"language":65,"meta":66,"style":66},"const users = [{ id: 1 }, { id: 7 }]\nusers.find(u => u.id === 7)        \u002F\u002F { id: 7 } — the object\nusers.findIndex(u => u.id === 7)   \u002F\u002F 1 — its index\nusers.includes({ id: 7 })          \u002F\u002F false different reference\n",[36,325,326,350,380,403],{"__ignoreMap":66},[70,327,328,330,333,335,338,341,344,347],{"class":72,"line":73},[70,329,77],{"class":76},[70,331,332],{"class":80}," users",[70,334,84],{"class":76},[70,336,337],{"class":87}," [{ id: ",[70,339,340],{"class":80},"1",[70,342,343],{"class":87}," }, { id: ",[70,345,346],{"class":80},"7",[70,348,349],{"class":87}," }]\n",[70,351,352,355,357,359,363,366,369,371,374,377],{"class":72,"line":113},[70,353,354],{"class":87},"users.",[70,356,314],{"class":119},[70,358,122],{"class":87},[70,360,362],{"class":361},"s4XuR","u",[70,364,365],{"class":76}," =>",[70,367,368],{"class":87}," u.id ",[70,370,42],{"class":76},[70,372,373],{"class":80}," 7",[70,375,376],{"class":87},")        ",[70,378,379],{"class":130},"\u002F\u002F { id: 7 } — the object\n",[70,381,382,384,386,388,390,392,394,396,398,400],{"class":72,"line":134},[70,383,354],{"class":87},[70,385,319],{"class":119},[70,387,122],{"class":87},[70,389,362],{"class":361},[70,391,365],{"class":76},[70,393,368],{"class":87},[70,395,42],{"class":76},[70,397,373],{"class":80},[70,399,284],{"class":87},[70,401,402],{"class":130},"\u002F\u002F 1 — its index\n",[70,404,405,407,409,412,414,417],{"class":72,"line":151},[70,406,354],{"class":87},[70,408,58],{"class":119},[70,410,411],{"class":87},"({ id: ",[70,413,346],{"class":80},[70,415,416],{"class":87}," })          ",[70,418,419],{"class":130},"\u002F\u002F false different reference\n",[15,421,422,423,425,426,428,429,425,431,434,435,438,439,442],{},"Note ",[36,424,58],{},"\u002F",[36,427,38],{}," compare by identity, so they can't find an object \"that looks the\nsame.\" Use ",[36,430,314],{},[36,432,433],{},"some"," with a predicate for value-based object searches. ",[36,436,437],{},"findLast"," and\n",[36,440,441],{},"findLastIndex"," search from the end — handy for \"most recent\" lookups.",[10,444,446],{"id":445},"the-sort-string-coercion-gotcha","The sort() string-coercion gotcha",[15,448,449,450,456],{},"Here's the big one. ",[19,451,452,455],{},[36,453,454],{},"Array.prototype.sort"," with no comparator converts elements to strings","\nand compares them by UTF-16 code unit. For numbers, this produces nonsense:",[61,458,460],{"className":63,"code":459,"language":65,"meta":66,"style":66},"[10, 1, 2, 20].sort()             \u002F\u002F [1, 10, 2, 20] \"10\" sorts before \"2\"\n[10, 1, 2, 20].sort((a, b) => a - b)   \u002F\u002F [1, 2, 10, 20]\n",[36,461,462,494],{"__ignoreMap":66},[70,463,464,466,469,471,473,475,478,480,483,485,488,491],{"class":72,"line":73},[70,465,250],{"class":87},[70,467,468],{"class":80},"10",[70,470,95],{"class":87},[70,472,340],{"class":80},[70,474,95],{"class":87},[70,476,477],{"class":80},"2",[70,479,95],{"class":87},[70,481,482],{"class":80},"20",[70,484,255],{"class":87},[70,486,487],{"class":119},"sort",[70,489,490],{"class":87},"()             ",[70,492,493],{"class":130},"\u002F\u002F [1, 10, 2, 20] \"10\" sorts before \"2\"\n",[70,495,496,498,500,502,504,506,508,510,512,514,516,519,522,524,527,530,533,536,539,542],{"class":72,"line":113},[70,497,250],{"class":87},[70,499,468],{"class":80},[70,501,95],{"class":87},[70,503,340],{"class":80},[70,505,95],{"class":87},[70,507,477],{"class":80},[70,509,95],{"class":87},[70,511,482],{"class":80},[70,513,255],{"class":87},[70,515,487],{"class":119},[70,517,518],{"class":87},"((",[70,520,521],{"class":361},"a",[70,523,95],{"class":87},[70,525,526],{"class":361},"b",[70,528,529],{"class":87},") ",[70,531,532],{"class":76},"=>",[70,534,535],{"class":87}," a ",[70,537,538],{"class":76},"-",[70,540,541],{"class":87}," b)   ",[70,543,544],{"class":130},"\u002F\u002F [1, 2, 10, 20]\n",[15,546,547,550],{},[19,548,549],{},"Always pass a comparator when sorting numbers."," This default trips up nearly every\ndeveloper at least once.",[10,552,554],{"id":553},"writing-comparators","Writing comparators",[15,556,557,558,561,562,564,565,568,569,571,572,574],{},"A comparator returns a ",[19,559,560],{},"negative"," number if ",[36,563,521],{}," should come first, ",[19,566,567],{},"positive"," if ",[36,570,526],{},"\nshould, and ",[36,573,195],{}," to keep their order.",[61,576,578],{"className":63,"code":577,"language":65,"meta":66,"style":66},"arr.sort((a, b) => a - b)   \u002F\u002F ascending numbers\narr.sort((a, b) => b - a)   \u002F\u002F descending numbers\n",[36,579,580,608],{"__ignoreMap":66},[70,581,582,585,587,589,591,593,595,597,599,601,603,605],{"class":72,"line":73},[70,583,584],{"class":87},"arr.",[70,586,487],{"class":119},[70,588,518],{"class":87},[70,590,521],{"class":361},[70,592,95],{"class":87},[70,594,526],{"class":361},[70,596,529],{"class":87},[70,598,532],{"class":76},[70,600,535],{"class":87},[70,602,538],{"class":76},[70,604,541],{"class":87},[70,606,607],{"class":130},"\u002F\u002F ascending numbers\n",[70,609,610,612,614,616,618,620,622,624,626,629,631,634],{"class":72,"line":113},[70,611,584],{"class":87},[70,613,487],{"class":119},[70,615,518],{"class":87},[70,617,521],{"class":361},[70,619,95],{"class":87},[70,621,526],{"class":361},[70,623,529],{"class":87},[70,625,532],{"class":76},[70,627,628],{"class":87}," b ",[70,630,538],{"class":76},[70,632,633],{"class":87}," a)   ",[70,635,636],{"class":130},"\u002F\u002F descending numbers\n",[15,638,639,640,643,644,647,648,425,650,652,653,656],{},"The ",[36,641,642],{},"a - b"," subtraction trick works only for numbers. Don't return a boolean (",[36,645,646],{},"a > b",") — it\ncoerces to ",[36,649,195],{},[36,651,340],{},", never negative, so the sort is broken. For strings, use ",[36,654,655],{},"localeCompare",":",[61,658,660],{"className":63,"code":659,"language":65,"meta":66,"style":66},"words.sort((a, b) => a.localeCompare(b))   \u002F\u002F human-friendly string order\n",[36,661,662],{"__ignoreMap":66},[70,663,664,667,669,671,673,675,677,679,681,684,686,689],{"class":72,"line":73},[70,665,666],{"class":87},"words.",[70,668,487],{"class":119},[70,670,518],{"class":87},[70,672,521],{"class":361},[70,674,95],{"class":87},[70,676,526],{"class":361},[70,678,529],{"class":87},[70,680,532],{"class":76},[70,682,683],{"class":87}," a.",[70,685,655],{"class":119},[70,687,688],{"class":87},"(b))   ",[70,690,691],{"class":130},"\u002F\u002F human-friendly string order\n",[10,693,695],{"id":694},"sort-mutates-beware","sort mutates — beware",[15,697,698,700,701,704,705,708],{},[36,699,487],{}," (and ",[36,702,703],{},"reverse",") sort ",[19,706,707],{},"in place"," and return the same array reference. If the array is\nshared, you've just mutated everyone's copy.",[61,710,712],{"className":63,"code":711,"language":65,"meta":66,"style":66},"const a = [3, 1, 2]\nconst sorted = a.sort((x, y) => x - y)\nsorted === a   \u002F\u002F true original mutated\n\nconst safe = a.toSorted((x, y) => x - y)   \u002F\u002F ES2023 new array, a untouched\nconst safe2 = [...a].sort((x, y) => x - y) \u002F\u002F copy-then-sort\n",[36,713,714,737,772,785,791,827],{"__ignoreMap":66},[70,715,716,718,720,722,724,727,729,731,733,735],{"class":72,"line":73},[70,717,77],{"class":76},[70,719,81],{"class":80},[70,721,84],{"class":76},[70,723,88],{"class":87},[70,725,726],{"class":80},"3",[70,728,95],{"class":87},[70,730,340],{"class":80},[70,732,95],{"class":87},[70,734,477],{"class":80},[70,736,110],{"class":87},[70,738,739,741,744,746,748,750,752,755,757,760,762,764,767,769],{"class":72,"line":113},[70,740,77],{"class":76},[70,742,743],{"class":80}," sorted",[70,745,84],{"class":76},[70,747,683],{"class":87},[70,749,487],{"class":119},[70,751,518],{"class":87},[70,753,754],{"class":361},"x",[70,756,95],{"class":87},[70,758,759],{"class":361},"y",[70,761,529],{"class":87},[70,763,532],{"class":76},[70,765,766],{"class":87}," x ",[70,768,538],{"class":76},[70,770,771],{"class":87}," y)\n",[70,773,774,777,779,782],{"class":72,"line":134},[70,775,776],{"class":87},"sorted ",[70,778,42],{"class":76},[70,780,781],{"class":87}," a   ",[70,783,784],{"class":130},"\u002F\u002F true original mutated\n",[70,786,787],{"class":72,"line":151},[70,788,790],{"emptyLinePlaceholder":789},true,"\n",[70,792,793,795,798,800,802,805,807,809,811,813,815,817,819,821,824],{"class":72,"line":168},[70,794,77],{"class":76},[70,796,797],{"class":80}," safe",[70,799,84],{"class":76},[70,801,683],{"class":87},[70,803,804],{"class":119},"toSorted",[70,806,518],{"class":87},[70,808,754],{"class":361},[70,810,95],{"class":87},[70,812,759],{"class":361},[70,814,529],{"class":87},[70,816,532],{"class":76},[70,818,766],{"class":87},[70,820,538],{"class":76},[70,822,823],{"class":87}," y)   ",[70,825,826],{"class":130},"\u002F\u002F ES2023 new array, a untouched\n",[70,828,830,832,835,837,839,842,845,847,849,851,853,855,857,859,861,863,866],{"class":72,"line":829},6,[70,831,77],{"class":76},[70,833,834],{"class":80}," safe2",[70,836,84],{"class":76},[70,838,88],{"class":87},[70,840,841],{"class":76},"...",[70,843,844],{"class":87},"a].",[70,846,487],{"class":119},[70,848,518],{"class":87},[70,850,754],{"class":361},[70,852,95],{"class":87},[70,854,759],{"class":361},[70,856,529],{"class":87},[70,858,532],{"class":76},[70,860,766],{"class":87},[70,862,538],{"class":76},[70,864,865],{"class":87}," y) ",[70,867,868],{"class":130},"\u002F\u002F copy-then-sort\n",[15,870,871,872,874],{},"In immutable contexts (React state), always copy first or use ",[36,873,804],{},".",[10,876,878],{"id":877},"stable-sort-and-multi-key-sorting","Stable sort and multi-key sorting",[15,880,881,882,884,885,888,889,892],{},"Since ES2019, ",[36,883,487],{}," is guaranteed ",[19,886,887],{},"stable",": elements the comparator treats as equal keep\ntheir original relative order. This makes ",[19,890,891],{},"multi-key sorting"," reliable — sort by the\nlowest-priority key first, then the next, and so on.",[61,894,896],{"className":63,"code":895,"language":65,"meta":66,"style":66},"people.sort((a, b) => a.firstName.localeCompare(b.firstName))  \u002F\u002F tiebreaker\n      .sort((a, b) => a.age - b.age)                            \u002F\u002F primary key\n\u002F\u002F stability keeps name order within each age group\n",[36,897,898,928,958],{"__ignoreMap":66},[70,899,900,903,905,907,909,911,913,915,917,920,922,925],{"class":72,"line":73},[70,901,902],{"class":87},"people.",[70,904,487],{"class":119},[70,906,518],{"class":87},[70,908,521],{"class":361},[70,910,95],{"class":87},[70,912,526],{"class":361},[70,914,529],{"class":87},[70,916,532],{"class":76},[70,918,919],{"class":87}," a.firstName.",[70,921,655],{"class":119},[70,923,924],{"class":87},"(b.firstName))  ",[70,926,927],{"class":130},"\u002F\u002F tiebreaker\n",[70,929,930,933,935,937,939,941,943,945,947,950,952,955],{"class":72,"line":113},[70,931,932],{"class":87},"      .",[70,934,487],{"class":119},[70,936,518],{"class":87},[70,938,521],{"class":361},[70,940,95],{"class":87},[70,942,526],{"class":361},[70,944,529],{"class":87},[70,946,532],{"class":76},[70,948,949],{"class":87}," a.age ",[70,951,538],{"class":76},[70,953,954],{"class":87}," b.age)                            ",[70,956,957],{"class":130},"\u002F\u002F primary key\n",[70,959,960],{"class":72,"line":134},[70,961,962],{"class":130},"\u002F\u002F stability keeps name order within each age group\n",[15,964,965,966,969],{},"A cleaner single-pass approach uses the ",[36,967,968],{},"||"," fall-through trick: return the first non-zero\ncomparison.",[61,971,973],{"className":63,"code":972,"language":65,"meta":66,"style":66},"people.sort((a, b) =>\n  a.lastName.localeCompare(b.lastName) ||   \u002F\u002F primary\n  a.firstName.localeCompare(b.firstName) || \u002F\u002F tiebreaker\n  a.age - b.age                             \u002F\u002F final tiebreaker\n)\n",[36,974,975,994,1009,1024,1037],{"__ignoreMap":66},[70,976,977,979,981,983,985,987,989,991],{"class":72,"line":73},[70,978,902],{"class":87},[70,980,487],{"class":119},[70,982,518],{"class":87},[70,984,521],{"class":361},[70,986,95],{"class":87},[70,988,526],{"class":361},[70,990,529],{"class":87},[70,992,993],{"class":76},"=>\n",[70,995,996,999,1001,1004,1006],{"class":72,"line":113},[70,997,998],{"class":87},"  a.lastName.",[70,1000,655],{"class":119},[70,1002,1003],{"class":87},"(b.lastName) ",[70,1005,968],{"class":76},[70,1007,1008],{"class":130},"   \u002F\u002F primary\n",[70,1010,1011,1014,1016,1019,1021],{"class":72,"line":134},[70,1012,1013],{"class":87},"  a.firstName.",[70,1015,655],{"class":119},[70,1017,1018],{"class":87},"(b.firstName) ",[70,1020,968],{"class":76},[70,1022,1023],{"class":130}," \u002F\u002F tiebreaker\n",[70,1025,1026,1029,1031,1034],{"class":72,"line":151},[70,1027,1028],{"class":87},"  a.age ",[70,1030,538],{"class":76},[70,1032,1033],{"class":87}," b.age                             ",[70,1035,1036],{"class":130},"\u002F\u002F final tiebreaker\n",[70,1038,1039],{"class":72,"line":168},[70,1040,1041],{"class":87},")\n",[10,1043,1045],{"id":1044},"locale-aware-and-natural-sorting","Locale-aware and natural sorting",[15,1047,1048,1050,1051,1054,1055,1058],{},[36,1049,655],{}," accepts options for case-insensitive and \"natural\" numeric sorting (so\n",[36,1052,1053],{},"file2"," comes before ",[36,1056,1057],{},"file10","):",[61,1060,1062],{"className":63,"code":1061,"language":65,"meta":66,"style":66},"['file10', 'file2'].sort((a, b) =>\n  a.localeCompare(b, undefined, { numeric: true }))   \u002F\u002F ['file2', 'file10']\n\nwords.sort((a, b) =>\n  a.localeCompare(b, undefined, { sensitivity: 'base' }))  \u002F\u002F case\u002Faccent-insensitive\n",[36,1063,1064,1092,1117,1121,1139],{"__ignoreMap":66},[70,1065,1066,1068,1071,1073,1076,1078,1080,1082,1084,1086,1088,1090],{"class":72,"line":73},[70,1067,250],{"class":87},[70,1069,1070],{"class":91},"'file10'",[70,1072,95],{"class":87},[70,1074,1075],{"class":91},"'file2'",[70,1077,255],{"class":87},[70,1079,487],{"class":119},[70,1081,518],{"class":87},[70,1083,521],{"class":361},[70,1085,95],{"class":87},[70,1087,526],{"class":361},[70,1089,529],{"class":87},[70,1091,993],{"class":76},[70,1093,1094,1097,1099,1102,1105,1108,1111,1114],{"class":72,"line":113},[70,1095,1096],{"class":87},"  a.",[70,1098,655],{"class":119},[70,1100,1101],{"class":87},"(b, ",[70,1103,1104],{"class":80},"undefined",[70,1106,1107],{"class":87},", { numeric: ",[70,1109,1110],{"class":80},"true",[70,1112,1113],{"class":87}," }))   ",[70,1115,1116],{"class":130},"\u002F\u002F ['file2', 'file10']\n",[70,1118,1119],{"class":72,"line":134},[70,1120,790],{"emptyLinePlaceholder":789},[70,1122,1123,1125,1127,1129,1131,1133,1135,1137],{"class":72,"line":151},[70,1124,666],{"class":87},[70,1126,487],{"class":119},[70,1128,518],{"class":87},[70,1130,521],{"class":361},[70,1132,95],{"class":87},[70,1134,526],{"class":361},[70,1136,529],{"class":87},[70,1138,993],{"class":76},[70,1140,1141,1143,1145,1147,1149,1152,1155,1158],{"class":72,"line":168},[70,1142,1096],{"class":87},[70,1144,655],{"class":119},[70,1146,1101],{"class":87},[70,1148,1104],{"class":80},[70,1150,1151],{"class":87},", { sensitivity: ",[70,1153,1154],{"class":91},"'base'",[70,1156,1157],{"class":87}," }))  ",[70,1159,1160],{"class":130},"\u002F\u002F case\u002Faccent-insensitive\n",[15,1162,1163,1164,1167,1168,1171,1172,1174],{},"For large arrays, build a reusable ",[36,1165,1166],{},"Intl.Collator"," and pass its ",[36,1169,1170],{},"compare"," method — it's much\nfaster than calling ",[36,1173,655],{}," per pair.",[10,1176,1178],{"id":1177},"when-to-reach-for-a-set-or-map","When to reach for a Set or Map",[15,1180,1181,1182,425,1184,1186,1187,1190,1191,1196],{},"Repeated ",[36,1183,58],{},[36,1185,38],{}," lookups are ",[19,1188,1189],{},"O(n)"," each. If you search the same collection\nmany times, build a ",[19,1192,1193],{},[36,1194,1195],{},"Set"," once for O(1) membership tests.",[61,1198,1200],{"className":63,"code":1199,"language":65,"meta":66,"style":66},"const seen = new Set(bigArray)\nqueries.filter(q => seen.has(q))   \u002F\u002F O(1) per lookup\n",[36,1201,1202,1220],{"__ignoreMap":66},[70,1203,1204,1206,1209,1211,1214,1217],{"class":72,"line":73},[70,1205,77],{"class":76},[70,1207,1208],{"class":80}," seen",[70,1210,84],{"class":76},[70,1212,1213],{"class":76}," new",[70,1215,1216],{"class":119}," Set",[70,1218,1219],{"class":87},"(bigArray)\n",[70,1221,1222,1225,1228,1230,1233,1235,1238,1241,1244],{"class":72,"line":113},[70,1223,1224],{"class":87},"queries.",[70,1226,1227],{"class":119},"filter",[70,1229,122],{"class":87},[70,1231,1232],{"class":361},"q",[70,1234,365],{"class":76},[70,1236,1237],{"class":87}," seen.",[70,1239,1240],{"class":119},"has",[70,1242,1243],{"class":87},"(q))   ",[70,1245,1246],{"class":130},"\u002F\u002F O(1) per lookup\n",[15,1248,1249,1250,1253,1254,1256],{},"Likewise, if you constantly look elements up by a key, index them in a ",[36,1251,1252],{},"Map"," rather than\nscanning with ",[36,1255,314],{}," every time. Choosing the right data structure beats optimizing the\nsearch.",[10,1258,1260],{"id":1259},"key-takeaways","Key takeaways",[1262,1263,1264,1286,1297,1306,1315,1328],"ul",{},[1265,1266,1267,425,1269,1271,1272,1274,1275,1277,1278,1280,1281,1283,1284,874],"li",{},[36,1268,38],{},[36,1270,52],{}," find by ",[36,1273,42],{}," (return ",[36,1276,46],{}," when absent); ",[36,1279,58],{}," returns a\nboolean and, unlike ",[36,1282,38],{},", can find ",[36,1285,229],{},[1265,1287,1288,1289,425,1291,1293,1294,1296],{},"Use ",[36,1290,314],{},[36,1292,319],{}," for predicate\u002Fobject searches; ",[36,1295,58],{}," compares objects by\nidentity.",[1265,1298,1299,1302,1303],{},[36,1300,1301],{},"sort()"," with no comparator stringifies elements — ",[19,1304,1305],{},"always pass a comparator for numbers.",[1265,1307,1308,1309,1311,1312,1314],{},"Comparators return negative\u002Fpositive\u002Fzero; ",[36,1310,642],{}," for numbers, ",[36,1313,655],{}," for strings.",[1265,1316,1317,425,1319,1321,1322,425,1324,1327],{},[36,1318,487],{},[36,1320,703],{}," mutate in place; use ",[36,1323,804],{},[36,1325,1326],{},"toReversed"," or copy first for\nimmutability.",[1265,1329,1330,1331,1334,1335,425,1337,1339],{},"Sort is stable (ES2019+), enabling multi-key sorting; use ",[36,1332,1333],{},"Intl"," options for case-\ninsensitive and natural ordering, and a ",[36,1336,1195],{},[36,1338,1252],{}," for repeated lookups.",[15,1341,1342],{},"Search with the method that matches your equality needs, and sort with a deliberate\ncomparator — and the array's most notorious gotcha stops being a problem.",[1344,1345,1346],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":66,"searchDepth":113,"depth":113,"links":1348},[1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359],{"id":12,"depth":113,"text":13},{"id":29,"depth":113,"text":30},{"id":206,"depth":113,"text":207},{"id":305,"depth":113,"text":306},{"id":445,"depth":113,"text":446},{"id":553,"depth":113,"text":554},{"id":694,"depth":113,"text":695},{"id":877,"depth":113,"text":878},{"id":1044,"depth":113,"text":1045},{"id":1177,"depth":113,"text":1178},{"id":1259,"depth":113,"text":1260},"Learn to search and sort arrays in JavaScript — indexOf vs includes, the NaN gotcha, find, the notorious sort() string-coercion bug, comparators, stable sort and multi-key sorting.","medium","md","JavaScript","javascript",{},"\u002Fblog\u002Fjavascript-array-searching-sorting","\u002Fjavascript\u002Farrays\u002Fsearching-sorting",{"title":5,"description":1360},"blog\u002Fjavascript-array-searching-sorting","Searching & Sorting","Arrays & Iteration","arrays","2026-06-18","_7lS3jMNwPK0hFM6m_rh4hgCWt21JK_t-vKqbYJAC_0",1781808673080]