我正在为图形输出的基数计算最小值。我的一个数组输出的值为零,因此不符合要求,并返回undefined。
const data = [
{value:0},
{value:0},
{value:0} ];
const defaultMinThreshold = 0;
const minThreshold = _.min([parseFloat(_.minBy(_(data).filter(d => d.value > 0).value(), 'value').value) - 0.5, defaultMinThreshold]);
如果数据的值大于0
,例如
const data = [
{value:1},
{value:0},
{value:0} ];
这返回minThreshold
作为0
-这是预期的。当/如果所有值均为0
时,我需要它返回0
而不是返回未定义。
我需要添加一个条件,即在数据中搜索至少具有大于0的1个值的值,否则默认返回0。
JS小提琴-https://jsfiddle.net/0cps7q9j/
nb如您所见,我确实将值过滤为> 0
,我可以做一个>= 0
,但是对于在该数据集中可能为零的数组,这会将基数降低为0,因此无法更改。
过滤器的原因是数据是否具有
值const data = [
{value:4},
{value:4},
{value:3} ];
高于最小值将返回3,因此阈值将为3,并且图形将从3开始而不是零。
答案 0 :(得分:1)
如果您不必完全使用Lodash,则这里的内容实用且易读。如果愿意,您也可以将其转换为纯Lodash解决方案。
https://jsfiddle.net/0cps7q9j/11/
const data = [
{value:-1},
{value:'0'},
{value:1.234} ];
const defaultMinThreshold = 0;
const filteredDataValueArray = data.filter(obj => !isNaN(parseFloat(obj.value)) && parseFloat(obj.value) >= 0).map(obj => obj.value);
const minThreshold = _.min(filteredDataValueArray) || defaultMinThreshold;
console.log('filteredDataValueArray', filteredDataValueArray);
console.log('minThreshold', minThreshold);
答案 1 :(得分:1)
我认为,这样编写代码将更容易理解:
const values = data.map(d => d.value);
const hasNonZero = values.some(v => v > 0);
const minThreshold = hasNonZero ? _.min(values) : 0;
我只在_.min
中使用lodash,这在这里很方便。您也可以将其替换为Math.min(...values)
或Math.min.apply(null, values)
const dataSets = [
[
{ value: 0 },
{ value: 0 },
{ value: 0 }
],
[
{ value: 1 },
{ value: 0 },
{ value: 0 }
],
[
{ value: 4 },
{ value: 4 },
{ value: 3 }
]
];
function getMinThreshold(data) {
const values = data.map(d => d.value);
const hasNonZero = values.some(v => v > 0);
const minThreshold = hasNonZero ? Math.min(...values) : 0;
return minThreshold;
}
dataSets.forEach(data => console.log(getMinThreshold(data)))
答案 2 :(得分:0)
让我们打破逻辑,以更好地呈现正在发生的事情。我已经提取了代码,并在单独的行中分解了每个操作,因此更容易看到:
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>
这有点冗长,仅使用许多变量将它们传递给下一个函数。您可以通过几种方法将其删除。第一种选择是使用chaining
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
那样每次都对值进行操作。为简便起见,这使用functional form of Lodash,但是如果您通过_.rearg
和_.curry
传递函数,则可以使用普通的Lodash。无论如何,这是什么样子:
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)
,依此类推,除了它定义了 process 之外,您可以在以后提供input
,然后依次传递。
答案 3 :(得分:0)
使用_.minBy
使用lodash的简洁方法:
const data = [ [ { value: 0 }, { value: 0 }, { value: 0 } ], [ { value: 1 }, { value: 0 }, { value: 0 } ], [ { value: 4 }, { value: 4 }, { value: 3 } ] ];
const result = _.map(data, x => _.minBy(x, 'value').value)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>