diff --git a/README.md b/README.md
index 2e34072e..72443fcd 100644
--- a/README.md
+++ b/README.md
@@ -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.
# d3.least(iterable[, comparator]) · [Source](https://github.com/d3/d3-array/blob/master/src/least.js), [Examples](https://observablehq.com/@d3/d3-least)
+
# d3.least(iterable[, accessor])
-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.
# d3.leastIndex(iterable[, comparator]) · [Source](https://github.com/d3/d3-array/blob/master/src/leastIndex.js), [Examples](https://observablehq.com/@d3/d3-least)
+
# d3.leastIndex(iterable[, comparator])
-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.
diff --git a/src/least.js b/src/least.js
index 53d470bc..a756abf4 100644
--- a/src/least.js
+++ b/src/least.js
@@ -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;
diff --git a/src/leastIndex.js b/src/leastIndex.js
index 3abf9058..2cd7a931 100644
--- a/src/leastIndex.js
+++ b/src/leastIndex.js
@@ -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;
diff --git a/test/least-test.js b/test/least-test.js
index 531c78b7..34407df5 100644
--- a/test/least-test.js
+++ b/test/least-test.js
@@ -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();
diff --git a/test/leastIndex-test.js b/test/leastIndex-test.js
index 472fcb03..407cb606 100644
--- a/test/leastIndex-test.js
+++ b/test/leastIndex-test.js
@@ -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();