Давайте разберем логику, чтобы лучше представить, что происходит.Я извлек код и разбил каждую операцию на отдельной строке, чтобы было легче увидеть:
const data = [
{value:0},
{value:0},
{value:0} ];
const defaultMinThreshold = 0;
const filterResult = _(data).filter(d => d.value > 0).value();
const minByResult = _.minBy(filterResult, 'value');
const minValue = minByResult.value;
const parsedValue = parseFloat(minValue);
const processedValue = parsedValue - 0.5;
const pair = [processedValue, defaultMinThreshold]
const minThreshold = _.min(pair);
Сначала я собираюсь рассмотреть некоторые проблемы и поговорить о некоторых упрощениях, которые можно сделать.
_(data).filter(d => d.value > 0).value()
Это немного излишне, а также несовместимо с другими вызовами lodash.Лучше сделать _.filter(data, d => d.value > 0)
- он и короче, и согласован.
const filterResult = _(data).filter(d => d.value > 0).value();
const minByResult = _.minBy(filterResult, 'value');
const minValue = minByResult.value;
Все три строки работают только со свойством value
и, наконец, извлекают из него число.Поскольку нет необходимости продолжать работать с объектами, вы можете извлечь value
и работать с ним напрямую.Весь раздел превращается в
const mapResult = _.map(data, 'value');
const filterResult = _.filter(mapResult, d => d > 0);
const minValue = _.min(filterResult);
Кроме того, вся проблема связана с minValue
- если у вас есть пустой массив и вы пытаетесь использовать _.min
или _.minBy
, вы получите undefined
.Я вернусь к этому.
const parsedValue = parseFloat(minValue);
Это не нужно.minValue
уже будет числом.У JS есть один тип чисел, он уже с плавающей точкой - нет «приведения» к целому числу с плавающей точкой или наоборот.Таким образом, нет необходимости в разборе.Вся строка может быть удалена.
const processedValue = minValue - 0.5;
Итак, зная, что minValue
может быть undefined
, есть некоторые вещи, которые можно сделать здесь, чтобы исправить это.Вы можете проверить undefined
, возможно, используя троичный minValue ? minValue : 0 - 0.5
, но мне легче всегда гарантировать, что вы возвращаете число из _.min
, даже если он пытается обработать пустой массив.
const minValue = _.min(filterResult) || 0; //if the first value is falsey (undefined), return zero
const processedValue = minValue - 0.5; //you might end up with a result of -0.5
const clampedValue = _.clamp(processedValue, 0, Infinity); //ensures the value is [0,) - zero (inclusive) to unbound maxiumum
Собрав все вместе, вы получите
const data = [
{value:0},
{value:0},
{value:0} ];
const defaultMinThreshold = 0;
const mapResult = _.map(data, 'value');
const filterResult = _.filter(mapResult, d => d > 0);
const minValue = _.min(filterResult) || 0;
const processedValue = minValue - 0.5;
const clampedValue = _.clamp(processedValue, 0, Infinity);
const pair = [clampedValue, defaultMinThreshold];
const minThreshold = _.min(pair);
console.log(minThreshold)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
Это немного многословно и использует много переменных только для передачи их следующей функции.Вы можете вырезать их несколькими способами.Первый вариант - использование цепочка
const data = [
{value:0},
{value:0},
{value:0} ];
const defaultMinThreshold = 0;
var processedValue = _.chain(data)
.map('value')
.filter(d => d > 0)
.sort()
.take(1) //min() breaks the array chaining, so doing sort() -> take(1) ensures we can continue
.map(x => x - 0.5) //not checking for "undefined" because an empty array won't be further processed
.map(_.clamp) //the second and third argument to _clamp are optional and omitting them is the same as passing 0 and Infinity
.value()[0];
//this will be undefined because we're getting index zero of an empty array
console.log("processedValue", processedValue);
const pair = [processedValue, defaultMinThreshold];
//the minimum of undefined and zero is zero. So you don't need extra checks
const minThreshold = _.min(pair);
console.log("minThreshold", minThreshold)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
Я оставил clamp
в этом методе, но он может быть ненужным.Поскольку массив нулей обрабатывается автоматически, единственный способ получить результат, меньший нуля, - это если у вас есть минимальное значение, скажем 0.3
, поэтому, когда вы вычтете из него 0.5
, вы закончитес негативом.Если это невозможно, вы можете опустить clamp
.
. Выше будет работать с массивом все время, пока он не завершит работу и не получит значение.Альтернативой является использование .min()
, которое, как я уже говорил, нарушает цепочку массивов, поскольку возвращает одно значение.Это означает, что вы больше не можете использовать .map()
, что лично мне кажется немного противоречивым.Просто чтобы проиллюстрировать, что происходит потом, здесь, как работать с одним значением.
const data = [
{value:0},
{value:0},
{value:0} ];
const defaultMinThreshold = 0;
var processedValue = _.chain(data)
.map('value')
.filter(d => d > 0)
.min()
.thru(x => x - 0.5) //if using .min() then you can use .thru to manipulate the single value
.thru(_.clamp)
.value();
//in this case, we get NaN because of undefined - 0.5
console.log("processedValue", processedValue);
const pair = [processedValue, defaultMinThreshold];
//the minimum of NaN and zero is still zero
const minThreshold = _.min(pair);
console.log("minThreshold", minThreshold)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
Еще один способ добиться того же - использовать конвейер обработки функций вместо того, чтобы каждый раз работать со значением, как при _.chain
.При этом для краткости используется функциональная форма Lodash , но вы можете использовать обычный Lodash, если передаете функции через _.rearg
и _.curry
.В любом случае, вот как это выглядит:
const data = [
{value:0},
{value:0},
{value:0} ];
const defaultMinThreshold = 0;
const processChain = _.flow( //compose all functions together
_.map('value'),
_.filter(d => d > 0),
_.min,
x => x || 0,
x => x - 0.5,
_.clamp(0)(Infinity)
);
const processedValue = processChain(data);
console.log("processedValue", processedValue)
const pair = [processedValue, defaultMinThreshold];
const minThreshold = _.min(pair);
console.log("minThreshold", minThreshold)
<script src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>
Это на самом деле намного ближе к тому, как работал ваш код и мой исходный код.Способ _.flow
работает так, чтобы по существу сделать следующее
aResult = a(input);
bResult = b(aResult)
cResult = c(bResult)
и т. Д., За исключением того, что он определяет процесс , затем вы можете позже предоставить input
, который будет, в свою очередь, впоследствии будет передан.