Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,25 +127,29 @@ Returns the standard deviation, defined as the square root of the [bias-correcte
Methods for searching arrays for a specific element.

<a name="least" href="#least">#</a> d3.<b>least</b>(<i>iterable</i>[, <i>comparator</i>]) · [Source](https://github.com/d3/d3-array/blob/master/src/least.js), [Examples](https://observablehq.com/@d3/d3-least)
<br><a name="least" href="#least">#</a> d3.<b>least</b>(<i>iterable</i>[, <i>accessor</i>])

Returns the least element of the specified *iterable* according to the specified *comparator*. If the given *iterable* contains no comparable elements (*i.e.*, the comparator returns NaN when comparing each element to itself), returns undefined. If *comparator* is not specified, it defaults to [ascending](#ascending). For example:
Returns the least element of the specified *iterable* according to the specified *comparator* or *accessor*. If the given *iterable* contains no comparable elements (*i.e.*, the comparator returns NaN when comparing each element to itself), returns undefined. If *comparator* is not specified, it defaults to [ascending](#ascending). For example:

```js
const array = [{foo: 42}, {foo: 91}];
d3.least(array, (a, b) => a.foo - b.foo); // {foo: 42}
d3.least(array, (a, b) => b.foo - a.foo); // {foo: 91}
d3.least(array, a => a.foo); // {foo: 42}
```

This function is similar to [min](#min), except it allows the use of a comparator rather than an accessor.

<a name="leastIndex" href="#leastIndex">#</a> d3.<b>leastIndex</b>(<i>iterable</i>[, <i>comparator</i>]) · [Source](https://github.com/d3/d3-array/blob/master/src/leastIndex.js), [Examples](https://observablehq.com/@d3/d3-least)
<br><a name="leastIndex" href="#leastIndex">#</a> d3.<b>leastIndex</b>(<i>iterable</i>[, <i>comparator</i>])

Returns the index of the least element of the specified *iterable* according to the specified *comparator*. If the given *iterable* contains no comparable elements (*i.e.*, the comparator returns NaN when comparing each element to itself), returns -1. If *comparator* is not specified, it defaults to [ascending](#ascending). For example:
Returns the index of the least element of the specified *iterable* according to the specified *comparator* or *accessor*. If the given *iterable* contains no comparable elements (*i.e.*, the comparator returns NaN when comparing each element to itself), returns -1. If *comparator* is not specified, it defaults to [ascending](#ascending). For example:

```js
const array = [{foo: 42}, {foo: 91}];
d3.leastIndex(array, (a, b) => a.foo - b.foo); // 0
d3.leastIndex(array, (a, b) => b.foo - a.foo); // 1
d3.leastIndex(array, a => a.foo); // 0
```

This function is similar to [minIndex](#minIndex), except it allows the use of a comparator rather than an accessor.
Expand Down
26 changes: 20 additions & 6 deletions src/least.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,26 @@ import ascending from "./ascending.js";
export default function least(values, compare = ascending) {
let min;
let defined = false;
for (const value of values) {
if (defined
? compare(value, min) < 0
: compare(value, value) === 0) {
min = value;
defined = true;
if (compare.length === 1) {
let minValue;
for (const element of values) {
const value = compare(element);
if (defined
? ascending(value, minValue) < 0
: ascending(value, value) === 0) {
min = element;
minValue = value;
defined = true;
}
}
} else {
for (const value of values) {
if (defined
? compare(value, min) < 0
: compare(value, value) === 0) {
min = value;
defined = true;
}
}
}
return min;
Expand Down
27 changes: 20 additions & 7 deletions src/leastIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,26 @@ export default function leastIndex(values, compare = ascending) {
let min;
let minIndex = -1;
let index = -1;
for (const value of values) {
++index;
if (minIndex < 0
? compare(value, value) === 0
: compare(value, min) < 0) {
min = value;
minIndex = index;
if (compare.length === 1) {
for (const element of values) {
++index;
const value = compare(element);
if (minIndex < 0
? ascending(value, value) === 0
: ascending(value, min) < 0) {
min = value;
minIndex = index;
}
}
} else {
for (const value of values) {
++index;
if (minIndex < 0
? compare(value, value) === 0
: compare(value, min) < 0) {
min = value;
minIndex = index;
}
}
}
return minIndex;
Expand Down
7 changes: 7 additions & 0 deletions test/least-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ tape("least(array, compare) compares using the specified compare function", func
test.end();
});

tape("least(array, accessor) uses the specified accessor function", function(test) {
var a = {name: "a", v: 42}, b = {name: "b", v: 0.42};
test.deepEqual(arrays.least([a, b], d => d.name), a);
test.deepEqual(arrays.least([a, b], d => d.v), b);
test.end();
});

tape("least(array) returns undefined if the array is empty", function(test) {
test.strictEqual(arrays.least([]), undefined);
test.end();
Expand Down
7 changes: 7 additions & 0 deletions test/leastIndex-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ tape("leastIndex(array, compare) compares using the specified compare function",
test.end();
});

tape("leastIndex(array, accessor) uses the specified accessor function", function(test) {
var a = {name: "a", v: 42}, b = {name: "b", v: 0.42};
test.deepEqual(arrays.leastIndex([a, b], d => d.name), 0);
test.deepEqual(arrays.leastIndex([a, b], d => d.v), 1);
test.end();
});

tape("leastIndex(array) returns -1 if the array is empty", function(test) {
test.strictEqual(arrays.leastIndex([]), -1);
test.end();
Expand Down