{"_id":"@observablehq/array","_rev":"27-5a6b0f5b9d7b55038a9e417400ec56a4","name":"@observablehq/array","dist-tags":{"latest":"0.0.4"},"versions":{"0.0.1":{"name":"@observablehq/array","version":"0.0.1","keywords":["array","columnar"],"author":{"url":"https://observablehq.com","name":"Observable, Inc."},"license":"ISC","_id":"@observablehq/array@0.0.1","maintainers":[{"name":"jashkenas","email":"jashkenas@gmail.com"},{"name":"mbostock","email":"mike@ocks.org"},{"name":"tmcw","email":"tom@macwright.org"}],"homepage":"https://github.com/observablehq/array","dist":{"shasum":"3faa45ba8f64bd3ec6fb6f6874021f474c9893a1","tarball":"https://registry.npmjs.org/@observablehq/array/-/array-0.0.1.tgz","fileCount":44,"integrity":"sha512-kubJHWm7LD5of8u3gRb+kSfmvFExhGX6VKX10DzBHyaWcTXF989oe/Pu7+XDhb0lUsYKHCZUX9enWmYJPRuLgg==","signatures":[{"sig":"MEQCIE/0t1BbsX5SLWrBJs1suC1BEKA8IBVkZ6MYVYWeYu6XAiApLwcV1rq/homeMtlLywVCbUfNPyNgE3ZmB3lIwcg/7w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":21496},"main":"dist/array.cjs.js","unpkg":"dist/array.umd.js","module":"dist/array.es.js","scripts":{"test":"tape -r esm 'test/**/*-test.js'","build":"rm -rf dist && mkdir dist && rollup -c","prepublishOnly":"yarn build && yarn test"},"_npmUser":{"name":"mbostock","email":"mike@ocks.org"},"repository":{"url":"https://github.com/observablehq/array","type":"git"},"description":"Manipulate typed arrays.","directories":{},"licenseText":"Copyright 2018 Observable, Inc.\n\nPermission to use, copy, modify, and/or distribute this software for any purpose\nwith or without fee is hereby granted, provided that the above copyright notice\nand this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\nOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\nTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\nTHIS SOFTWARE.\n","_hasShrinkwrap":false,"devDependencies":{"esm":"^3.0.55","tape":"^4.9.1","rollup":"^0.62.0","tape-await":"^0.1.1","rollup-plugin-terser":"^1.0.1"},"_npmOperationalInternal":{"tmp":"tmp/array_0.0.1_1530286200600_0.5095927603040733","host":"s3://npm-registry-packages"}},"0.0.2":{"name":"@observablehq/array","version":"0.0.2","keywords":["array","columnar"],"author":{"url":"https://observablehq.com","name":"Observable, Inc."},"license":"ISC","_id":"@observablehq/array@0.0.2","maintainers":[{"name":"jashkenas","email":"jashkenas@gmail.com"},{"name":"mbostock","email":"mike@ocks.org"},{"name":"tmcw","email":"tom@macwright.org"}],"homepage":"https://github.com/observablehq/array","dist":{"shasum":"8697ba723d254500d271b8ceb4113f4dcd09baee","tarball":"https://registry.npmjs.org/@observablehq/array/-/array-0.0.2.tgz","fileCount":46,"integrity":"sha512-8esKI8kUK9imEqD5tJzH/6Q5ouAdRVZMl6Bjj4jck+xT/rGaob1ca6kWIamOYKK5QD2/2tSeIAkHZF4RC3O9bg==","signatures":[{"sig":"MEQCIAI8jtxRDUudgbqIQH0b4XQN6DX7WtFCNZBv65OzgaVeAiB7L9sLN5DsG1N6Ahrqu5N7DGSkWDeH3tEyQ8r6Gud0Yw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":29554},"main":"dist/array.cjs.js","unpkg":"dist/array.umd.js","module":"dist/array.es.js","scripts":{"test":"tape -r esm 'test/**/*-test.js'","build":"rm -rf dist && mkdir dist && rollup -c","prepublishOnly":"yarn build && yarn test"},"_npmUser":{"name":"mbostock","email":"mike@ocks.org"},"repository":{"url":"https://github.com/observablehq/array","type":"git"},"description":"Manipulate typed arrays.","directories":{},"licenseText":"Copyright 2018 Observable, Inc.\n\nPermission to use, copy, modify, and/or distribute this software for any purpose\nwith or without fee is hereby granted, provided that the above copyright notice\nand this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\nOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\nTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\nTHIS SOFTWARE.\n","_hasShrinkwrap":false,"devDependencies":{"esm":"^3.0.55","tape":"^4.9.1","rollup":"^0.62.0","tape-await":"^0.1.1","rollup-plugin-terser":"^1.0.1"},"_npmOperationalInternal":{"tmp":"tmp/array_0.0.2_1530292211526_0.9176756204509877","host":"s3://npm-registry-packages"}},"0.0.3":{"name":"@observablehq/array","version":"0.0.3","keywords":["array","columnar"],"author":{"url":"https://observablehq.com","name":"Observable, Inc."},"license":"ISC","_id":"@observablehq/array@0.0.3","maintainers":[{"name":"jashkenas","email":"jashkenas@gmail.com"},{"name":"mbostock","email":"mike@ocks.org"},{"name":"tmcw","email":"tom@macwright.org"}],"homepage":"https://github.com/observablehq/array","dist":{"shasum":"2f672bfc67043d217a9f5aafb68ca015e74809e1","tarball":"https://registry.npmjs.org/@observablehq/array/-/array-0.0.3.tgz","fileCount":50,"integrity":"sha512-ZKTKEIePeB7yMfNvZKTvRH7Ez5tq0u/xS/3finTUmkC7JzvA2f1kXuJ/iYPmeRuDU87jpIN8U5GCV4SBw6yOxQ==","signatures":[{"sig":"MEYCIQDhCnEI/lkm6GeSUXPLTs/lb90gypcH1Vc140Hnm9js8wIhALag/hkanVj32juaUSq3VwIa/qKy9GAntUtgzA9LbbyQ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":47753},"main":"dist/array.cjs.js","unpkg":"dist/array.umd.js","module":"dist/array.es.js","scripts":{"test":"tape -r esm 'test/**/*-test.js'","build":"rm -rf dist && mkdir dist && rollup -c","prepublishOnly":"yarn build && yarn test"},"_npmUser":{"name":"mbostock","email":"mike@ocks.org"},"repository":{"url":"https://github.com/observablehq/array","type":"git"},"description":"Manipulate typed arrays.","directories":{},"licenseText":"Copyright 2018 Observable, Inc.\n\nPermission to use, copy, modify, and/or distribute this software for any purpose\nwith or without fee is hereby granted, provided that the above copyright notice\nand this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\nOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\nTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\nTHIS SOFTWARE.\n","_hasShrinkwrap":false,"devDependencies":{"esm":"^3.0.55","tape":"^4.9.1","rollup":"^0.62.0","tape-await":"^0.1.1","rollup-plugin-terser":"^1.0.1"},"_npmOperationalInternal":{"tmp":"tmp/array_0.0.3_1530299319943_0.310904318340508","host":"s3://npm-registry-packages"}},"0.0.4":{"name":"@observablehq/array","version":"0.0.4","keywords":["array","columnar"],"author":{"url":"https://observablehq.com","name":"Observable, Inc."},"license":"ISC","_id":"@observablehq/array@0.0.4","maintainers":[{"name":"jashkenas","email":"jashkenas@gmail.com"},{"name":"mbostock","email":"mike@ocks.org"},{"name":"tmcw","email":"tom@macwright.org"}],"homepage":"https://github.com/observablehq/array","dist":{"shasum":"533b37ec63eea0525ad082c08dab656660d4fb5b","tarball":"https://registry.npmjs.org/@observablehq/array/-/array-0.0.4.tgz","fileCount":51,"integrity":"sha512-LqjwzOp2x4TkfL66VfMK3olAfgFS9fsg66nFVjQHV0+G+cYl33vkNVW+u4WquiUxuCQVyuAZ56qxthnR3LE4nA==","signatures":[{"sig":"MEUCIFl640bmA4aka2LlVEoZtyBllEu6xkG4Ui4ikKJNwF2WAiEAzTp1qo0ZuVVStFve7sQSg7DRQ0zaLwuNgUp6T3GVUGk=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50712,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2T+OCRA9TVsSAnZWagAAn+AP/AvrcW+NMq8f+AHPoALR\nUN3Wyu/Km204I68GWnACNvZ85yQTtFvlM5tKicpSXcBBdkp98g2A2pjgbksi\nK5t+CF5yby0OFQCkYj1oP6ayuptjliYsqCI0HHOl8Wb5f0VZQwQQzD2gjF8R\n+LdmgDsAEDTu4fNXtp4NDo12nkGHb+L40N1nHwGEXGnF7B17QZMq1sKlBB9v\n0MU4PwRvtAgXb9ATtwdfks0jqu+NObKZQtqMY1/F+lOtpI2XTxkLx6O5zfpH\n8WVgu6/4qy6+3LstdAnGGKzqiQtKFli1DJEVS4uS1Z71NPw+vdLk4jzqWsLf\nnlQJu+CuKMLuH78GJIKLlA1avzUd6sDSdu8B7su6oaHO4T8AX0xeUzkb2txA\nXlXQpYv1qkJw9tDrAQM2cKy9ijE1qhTlg2E646LXZidCsSOmDgUpS4qA5rQw\nEaUVegy0oHvT4XhHYSnpK6RH1GgqSNjeCvRiuLz1H13P2SGONPijRSGEAkQ5\n56vVcvU8znI/J//1hIv7tLNZlNRyIwsCFVKpEWdXxW1Jylvc0XND+D0oN2tc\nzSs2XIvKmYRswt2yc25dAsvIeb8EakwvLtVZuFoIqrFYYgCpmQJC8r/UsUKx\nPkTX6uEC0GM13yrHMElhy1hjq3Uv1Kzu2xYp9JqMJB/b0wh+suD86ELDLUQP\nr2px\r\n=fi4u\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/array.cjs.js","unpkg":"dist/array.umd.js","module":"dist/array.es.js","scripts":{"test":"tape -r esm 'test/**/*-test.js'","build":"rm -rf dist && mkdir dist && rollup -c","prepublishOnly":"yarn build && yarn test"},"_npmUser":{"name":"mbostock","email":"mike@ocks.org"},"repository":{"url":"https://github.com/observablehq/array","type":"git"},"description":"Manipulate typed arrays.","directories":{},"licenseText":"Copyright 2018 Observable, Inc.\n\nPermission to use, copy, modify, and/or distribute this software for any purpose\nwith or without fee is hereby granted, provided that the above copyright notice\nand this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\nOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\nTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\nTHIS SOFTWARE.\n","_hasShrinkwrap":false,"devDependencies":{"esm":"^3.0.55","tape":"^4.9.1","rollup":"^0.62.0","tape-await":"^0.1.1","rollup-plugin-terser":"^1.0.1"},"_npmOperationalInternal":{"tmp":"tmp/array_0.0.4_1530299651319_0.960048403588565","host":"s3://npm-registry-packages"}}},"time":{"created":"2018-06-29T15:30:00.537Z","modified":"2026-04-06T17:49:30.084Z","0.0.1":"2018-06-29T15:30:00.654Z","0.0.2":"2018-06-29T17:10:11.600Z","0.0.3":"2018-06-29T19:08:40.024Z","0.0.4":"2018-06-29T19:14:11.496Z"},"author":{"url":"https://observablehq.com","name":"Observable, Inc."},"license":"ISC","homepage":"https://github.com/observablehq/array","keywords":["array","columnar"],"repository":{"url":"https://github.com/observablehq/array","type":"git"},"description":"Manipulate typed arrays.","maintainers":[{"email":"mike@ocks.org","name":"mbostock"},{"email":"visnup@gmail.com","name":"visnup"},{"email":"fil@rezo.net","name":"recifs"},{"email":"tophtucker@gmail.com","name":"tophtucker"}],"readme":"# @observablehq/array\n\nThis library provides methods for operating on columnar data represented as parallel arrays. Most operations involve computing an index—an array of integers, each in [0, *length* - 1]—and then using the index to derive new columns.\n\nhttps://beta.observablehq.com/@mbostock/manipulating-flat-arrays\n\n## API Reference\n\n### Taking\n\n<a href=\"#take\" name=\"take\">#</a> <b>take</b>(<i>values</i>, <i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/take.js \"Source\")\n\nReturns a new array of values from the specified *values* array according to the specified *index* array. The returned array is the same type as the specified *values* array.\n\n```js\ntake([\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"], [0, 2, 0, 1]) // [\"a\", \"c\", \"a\", \"b\"]\n```\n\n<a href=\"#taker\" name=\"taker\">#</a> <b>taker</b>(<i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/taker.js \"Source\")\n\nReturns a [take](#take)-like function that, when passed an array of *values*, returns a new array of values from the specified *values* array according to the specified *index* array. The returned array is the same type as the specified *values* array.\n\n```js\ntaker([0, 2, 0, 1])([\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]) // [\"a\", \"c\", \"a\", \"b\"]\n```\n\nThis method is often used to take multiple arrays simultaneously using [*array*.map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```js\nletter = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"]\n```\n```js\nname = [\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"]\n```\n```js\n[letter, name].map(taker([2, 1, 0])) // [[\"c\", \"b\", \"a\"], [\"Cee\", \"Bee\", \"Ay\"]]\n```\n\n<a href=\"#get\" name=\"get\">#</a> <b>get</b>(<i>i</i>) [<>](https://github.com/observablehq/array/blob/master/src/get.js \"Source\")\n\nReturns a [take](#take)-like function that, when passed an array of *values*, returns the value from the specified *values* array with the specified index *i*.\n\n```js\nget(2)([\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]) // \"c\"\n```\n\nThis method is often used to get from multiple arrays simultaneously using [*array*.map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```js\nletter = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"]\n```\n```js\nname = [\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"]\n```\n```js\n[letter, name].map(get(2)) // [\"c\", \"Cee\"]\n```\n\n<a href=\"#slice\" name=\"slice\">#</a> <b>slice</b>([<i>start</i>[, <i>stop</i>]]) [<>](https://github.com/observablehq/array/blob/master/src/slice.js \"Source\")\n\nReturns a function that when passed an array, returns a slice of the array according to the specified *start* and *stop* index. The returned function is equivalent to calling [*array*.slice](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/slice).\n\n```js\nslice(0, 3)([\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"]) // [\"Ay\", \"Bee\", \"Cee\"]\n```\n\nThis method is often used to take multiple arrays simultaneously using [*array*.map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```js\nletter = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"]\n```\n```js\nname = [\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"]\n```\n```js\n[letter, name].map(slice(0, 3)) // [[\"a\", \"b\", \"c\"], [\"Ay\", \"Bee\", \"Cee\"]]\n```\n\n### Summarizing\n\n<a href=\"#count\" name=\"count\">#</a> <b>count</b>(<i>values</i>) [<>](https://github.com/observablehq/array/blob/master/src/count.js \"Source\")\n\nReturns the number of numeric values in the specified *values* array.\n\n```js\ncount([1, \"N/A\", 2, NaN, 3]) // 3\n```\n\n<a href=\"#counti\" name=\"counti\">#</a> <b>counti</b>(<i>values</i>, <i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/counti.js \"Source\")\n\nReturns the number of numeric values in the subset of the specified *values* array in the specified *index* array. Equivalent to [count](#count)([take](#take)(*values*, *index*)).\n\n```js\ncounti([1, \"N/A\", 2, NaN, 3], [0, 1, 2]) // 2\n```\n\n<a href=\"#max\" name=\"max\">#</a> <b>max</b>(<i>values</i>) [<>](https://github.com/observablehq/array/blob/master/src/max.js \"Source\")\n\nReturns the maximum numeric value in the specified *values* array. For the corresponding index, see [top](#top).\n\n```js\nmax([1, \"N/A\", 2, NaN, 4.5]) // 4.5\n```\n\n<a href=\"#maxi\" name=\"maxi\">#</a> <b>maxi</b>(<i>values</i>, <i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/maxi.js \"Source\")\n\nReturns the maximum numeric value in the subset of the specified *values* array in the specified *index* array. For the corresponding index, see [topi](#topi).\n\n```js\nmaxi([1, \"N/A\", 2.5, NaN, 4], [0, 1, 2]) // 2\n```\n\n<a href=\"#min\" name=\"min\">#</a> <b>min</b>(<i>values</i>) [<>](https://github.com/observablehq/array/blob/master/src/min.js \"Source\")\n\nReturns the minimum numeric value in the specified *values* array. For the corresponding index, see [bottom](#bottom).\n\n```js\nmin([1, \"N/A\", 2, NaN, 4.5]) // 1\n```\n\n<a href=\"#mini\" name=\"mini\">#</a> <b>mini</b>(<i>values</i>, <i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/mini.js \"Source\")\n\nReturns the minimum numeric value in the subset of the specified *values* array in the specified *index* array. For the corresponding index, see [bottomi](#bottomi).\n\n```js\nmini([1.5, \"N/A\", 2, NaN, 4], [0, 1, 2]) // 1.5\n```\n\n<a href=\"#mean\" name=\"mean\">#</a> <b>mean</b>(<i>values</i>) [<>](https://github.com/observablehq/array/blob/master/src/mean.js \"Source\")\n\nReturns the arithmetic mean of the specified *values* array.\n\n```js\nmean([0, 1, 4, 8, NaN, 2]) // 3\n```\n\n<a href=\"#meani\" name=\"meani\">#</a> <b>meani</b>(<i>values</i>, <i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/meani.js \"Source\")\n\nReturns the arithmetic mean of the subset of the specified *values* array in the specified *index* array. Equivalent to [mean](#mean)([take](#take)(*values*, *index*)).\n\n```js\nmeani([NaN, 1, 3, 8, 3], [0, 1, 2, 3]) // 4\n```\n\n<a href=\"#median\" name=\"median\">#</a> <b>median</b>(<i>values</i>) [<>](https://github.com/observablehq/array/blob/master/src/median.js \"Source\")\n\nReturns the median of the specified *values* array. Equivalent to [quantile](#quantile)(*values*, 0.5).\n\n```js\nmedian([0, 1, 4, 8, NaN, 2]) // 2\n```\n\n<a href=\"#mediani\" name=\"mediani\">#</a> <b>mediani</b>(<i>values</i>, <i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/mediani.js \"Source\")\n\nReturns the median of the subset of the specified *values* array in the specified *index* array. Equivalent to [quantile](#quantile)([take](#take)(*values*, *index*), 0.5).\n\n```js\nmediani([0, 1, 4, 8, NaN, 2], [0, 1, 2, 3]) // 2.5\n```\n\n<a href=\"#quantile\" name=\"quantile\">#</a> <b>quantile</b>(<i>values</i>, <i>p</i>) [<>](https://github.com/observablehq/array/blob/master/src/quantile.js \"Source\")\n\nReturns the *p*-quantile of the specified *values* array with the specified *p* using the [R-7 method](https://en.wikipedia.org/wiki/Quantile#Quantiles_of_a_population).\n\n```js\nquantile([0, 1, 4, 8, NaN, 2], 0.5) // 2\n```\n\n<a href=\"#quantilei\" name=\"quantilei\">#</a> <b>quantilei</b>(<i>values</i>, <i>index</i>, <i>p</i>) [<>](https://github.com/observablehq/array/blob/master/src/quantilei.js \"Source\")\n\nReturns the *p*-quantile of the subset of the specified *values* array in the specified *index* array with the specified *p* using the [R-7 method](https://en.wikipedia.org/wiki/Quantile#Quantiles_of_a_population). Equivalent to [quantile](#quantile)([take](#take)(*values*, *index*), *p*).\n\n```js\nquantilei([0, 1, 4, 8, NaN, 2], [0, 1, 2, 3], 0.5) // 2\n```\n\n<a href=\"#sum\" name=\"sum\">#</a> <b>sum</b>(<i>values</i>) [<>](https://github.com/observablehq/array/blob/master/src/sum.js \"Source\")\n\nReturns the sum of the specified *values* array.\n\n```js\nsum([0, 1, 4, 8, NaN, 2]) // 15\n```\n\n<a href=\"#sumi\" name=\"sumi\">#</a> <b>sumi</b>(<i>values</i>, <i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/sumi.js \"Source\")\n\nReturns the sum of the subset of the specified *values* array in the specified *index* array. Equivalent to [sum](#sum)([take](#take)(*values*, *index*)).\n\n```js\nsumi([0, 1, 4, 8, NaN, 2], [0, 1, 2, 3]) // 13\n```\n\n### Sorting\n\n<a href=\"#bottom\" name=\"bottom\">#</a> <b>bottom</b>(<i>values</i>, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottom.js \"Source\")\n\nReturns the index of the specified *values* array with the corresponding least value according to the specified *order* comparator.\n\n```js\nbottom([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"]) // 7\n```\n\n<a href=\"#bottomi\" name=\"bottomi\">#</a> <b>bottomi</b>(<i>values</i>, <i>index</i>, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottomi.js \"Source\")\n\nReturns the index in the specified *index* array with the corresponding least value in the specified *values* array according to the specified *order* comparator. Equivalent to [bottom](#bottom)([take](#take)(*values*, *index*), *order*).\n\n```js\nbottomi([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"], [0, 2, 4, 6]) // 2\n```\n\n<a href=\"#bottoms\" name=\"bottoms\">#</a> <b>bottoms</b>(<i>values</i>, <i>k</i> = 5, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottoms.js \"Source\")\n\nReturns an array of the *k* indexes of the specified *values* array with the corresponding least values according to the specified *order* comparator.\n\n```js\nbottoms([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"], 3) // [7, 8, 5]\n```\n\n<a href=\"#bottomsi\" name=\"bottomsi\">#</a> <b>bottomsi</b>(<i>values</i>, <i>index</i>, <i>k</i> = 5, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottomsi.js \"Source\")\n\nReturns an array of the *k* indexes in the specified *index* array with the corresponding least values in the specified *values* array according to the specified *order* comparator. Equivalent to [bottoms](#bottoms)([take](#take)(*values*, *index*), *k*, *order*).\n\n```js\nbottomsi([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"], [0, 2, 4, 6], 2) // [2, 0]\n```\n\n<a href=\"#sort\" name=\"sort\">#</a> <b>sort</b>(<i>values</i>, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/sort.js \"Source\")\n\nReturns the indexes of the specified *values* array sorted according to the specified *order* comparator and array of *values*.\n\n```js\nsort([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"]) // [7, 8, 5, 2, 1, 0, 4, 6, 3, 9]\n```\n\n<a href=\"#sorti\" name=\"sorti\">#</a> <b>sorti</b>(<i>values</i>, <i>index</i>, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/sorti.js \"Source\")\n\nReturns a copy of the specified *index* array sorted according to the specified *order* comparator and array of *values*.\n\n```js\nsorti([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"], [0, 2, 4, 6]) // [2, 0, 4, 6]\n```\n\n<a href=\"#top\" name=\"top\">#</a> <b>top</b>(<i>values</i>, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/top.js \"Source\")\n\nReturns the index of the specified *values* array with the corresponding greatest value according to the specified *order* comparator.\n\n```js\ntop([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"]) // 9\n```\n\n<a href=\"#topi\" name=\"topi\">#</a> <b>topi</b>(<i>values</i>, <i>index</i>, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/topi.js \"Source\")\n\nReturns the index in the specified *index* array with the corresponding greatest value in the specified *values* array according to the specified *order* comparator. Equivalent to [top](#top)([take](#take)(*values*, *index*), *order*).\n\n```js\ntopi([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"], [0, 2, 4, 6]) // 6\n```\n\n<a href=\"#tops\" name=\"tops\">#</a> <b>tops</b>(<i>values</i>, <i>k</i> = 5, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/tops.js \"Source\")\n\nReturns an array of the *k* indexes of the specified *values* array with the corresponding greatest values according to the specified *order* comparator.\n\n```js\ntops([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"], 3) // [9, 3, 6]\n```\n\n<a href=\"#topsi\" name=\"topsi\">#</a> <b>topsi</b>(<i>values</i>, <i>index</i>, <i>k</i> = 5, <i>order</i> = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/topsi.js \"Source\")\n\nReturns an array of the *k* indexes in the specified *index* array with the corresponding greatest values in the specified *values* array according to the specified *order* comparator. Equivalent to [top](#top)([take](#take)(*values*, *index*), *k*, *order*).\n\n```js\ntopsi([\"f\", \"e\", \"d\", \"i\", \"g\", \"c\", \"h\", \"a\", \"b\", \"j\"], [0, 2, 4, 6], 2) // [6, 4]\n```\n\n### Arranging\n\n<a href=\"#reverse\" name=\"reverse\">#</a> <b>reverse</b>(<i>values</i>) [<>](https://github.com/observablehq/array/blob/master/src/reverse.js \"Source\")\n\nReturns a reversed copy of the specified *values* array. Like [*array*.reverse](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), but returns a copy.\n\n<a href=\"#shuffle\" name=\"shuffle\">#</a> <b>shuffle</b>(<i>length</i>) [<>](https://github.com/observablehq/array/blob/master/src/shuffle.js \"Source\")\n\nReturns an array of integers 0 … *length* - 1 in random order.\n\n<a href=\"#shufflei\" name=\"shufflei\">#</a> <b>shufflei</b>(<i>index</i>) [<>](https://github.com/observablehq/array/blob/master/src/shufflei.js \"Source\")\n\nReturns a shuffled copy of the specified *index* array.\n\n### Filtering\n\n<a href=\"#filter\" name=\"filter\">#</a> <b>filter</b>(<i>values</i>, <i>test</i>) [<>](https://github.com/observablehq/array/blob/master/src/filter.js \"Source\")\n\nReturns an array of indexes from the specified *values* array for which the specified *test* function returned truthy. The *test* function is passed a value from the *values* array, the corresponding index, and the *values* array itself.\n\n```js\nfilter([\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"], d => d.length === 2) // [0, 4, 5]\n```\n\n<a href=\"#filteri\" name=\"filteri\">#</a> <b>filteri</b>(<i>values</i>, <i>index</i>, <i>test</i>) [<>](https://github.com/observablehq/array/blob/master/src/filteri.js \"Source\")\n\nReturns the subset of the specified *index* for which the specified *test* function returned truthy. The *test* function is passed a value from the *values* array, the corresponding index, and the *values* array itself.\n\n```js\nfilteri([\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"], [0, 1, 2, 3], d => d.length === 2) // [0]\n```\n\n### Grouping\n\n<a href=\"#group\" name=\"group\">#</a> <b>group</b>(<i>values</i>, <i>key</i> = [identity](#identity)[, <i>value</i>]) [<>](https://github.com/observablehq/array/blob/master/src/group.js \"Source\")\n\nReturns a new Map where the keys of the map are computed by applying the specified *key* function to each element in the specified *values* array.\n\n```js\nname = [\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"]\n```\n```js\ngroup(name, d => d.length) // {2 => [\"Ay\", \"Ee\", \"Ef\"], 3 => [\"Bee\", \"Cee\", \"Dee\", \"Gee\"]}\n```\n\nIf a *value* function is specified, it is invoked with the array of indexes for each entry in the returned map, and the returned map’s value is replaced by whatever the *value* function returns.\n\n```js\nletter = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"]\n```\n```js\ngroup(name, d => d.length, i => take(letter, i)) // {2 => [\"a\", \"e\", \"f\"], 3 => [\"b\", \"c\", \"d\", \"g\"]}\n```\n```js\ngroup(name, d => d.length, i => i.length) // {2 => 3, 3 => 4}\n```\n\n<a href=\"#groupi\" name=\"groupi\">#</a> <b>groupi</b>(<i>values</i>, <i>index</i>, <i>key</i> = [identity](#identity)[, <i>value</i>]) [<>](https://github.com/observablehq/array/blob/master/src/groupi.js \"Source\")\n\nReturns a new Map where the keys of the map are computed by applying the specified *key* function to each element in the specified *values* array present in the specified *index* array.\n\n```js\nname = [\"Ay\", \"Bee\", \"Cee\", \"Dee\", \"Ee\", \"Ef\", \"Gee\"]\n```\n```js\ngroupi(name, [0, 1, 2], d => d.length) // {2 => [\"Ay\"], 3 => [\"Bee\", \"Cee\"]}\n```\n\nIf a *value* function is specified, it is invoked with the array of indexes for each entry in the returned map, and the returned map’s value is replaced by whatever the *value* function returns.\n\n```js\nletter = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"]\n```\n```js\ngroupi(name, [0, 1, 2], d => d.length, i => take(letter, i)) // {2 => [\"a\"], 3 => [\"b\", \"c\"]}\n```\n```js\ngroupi(name, [0, 1, 2], d => d.length, i => i.length) // {2 => 1, 3 => 2}\n```\n\n### Comparing\n\nThese functions are useful as the *order* argument to [sort](#sort), [top](#top) and [bottom](#bottom).\n\n<a href=\"#ascending\" name=\"ascending\">#</a> <b>ascending</b>(<i>a</i>, <i>b</i>) [<>](https://github.com/observablehq/array/blob/master/src/ascending.js \"Source\")\n\nReturns -1 if *a* is less than *b*, 1 if *a* is greater than *b*, 0 if *a* is equal to *b*, or NaN.\n\n<a href=\"#descending\" name=\"descending\">#</a> <b>descending</b>(<i>a</i>, <i>b</i>) [<>](https://github.com/observablehq/array/blob/master/src/descending.js \"Source\")\n\nReturns -1 if *b* is less than *a*, 1 if *b* is greater than *a*, 0 if *b* is equal to *a*, or NaN.\n\n### Other\n\n<a href=\"#identity\" name=\"identity\">#</a> <b>identity</b>(<i>x</i>) [<>](https://github.com/observablehq/array/blob/master/src/identity.js \"Source\")\n\nReturns *x*.\n\n<a href=\"#range\" name=\"range\">#</a> <b>range</b>([<i>start</i>, ]<i>stop</i>[, <i>step</i>]]) [<>](https://github.com/observablehq/array/blob/master/src/range.js \"Source\")\n\nReturns an array of integers starting at the specified inclusive *start* value and stopping before the specified exclusive *stop* value. If a *start* value is not specified, it defaults to zero; if a *step* value is not specified, it defaults to 1.\n","readmeFilename":"README.md"}