我们有三个不同的网页,其中包含用于添加主实体详细信息的网格。
Detail对象可以通过javascript表达
var detail = {
Description: 'Detail',
MinPercentage: 0,
MaxPercentage: 20
}
现在,我们要在发送到服务器之前验证这些详细信息。
验证
- 不得有任何交集。即 detail('Detail1', 0, 20) 和 detail('Detail2', 15, 30) 无效,因为 15 到 20 是常见的。
- 细节保存从给定的最小值到给定的最大值的值。即,detail('Detail1', 0, 20) 和 detail('Detail2', 20, 40) 保存从 0 到 40 的值。如果给定最小值为 0,给定最大值为 40,则它们有效。
对功能的期望
- 因为我想编写一个在多个地方使用的函数,所以应该尽可能通用。
然后,我编写了一个名为 areIntervalsValid 的函数,但我不确定如何处理输入错误的调用、抛出异常、返回最佳结构化结果,而且我想知道执行的最佳方式是什么验证。
// Returns array of detail object to test.
var getDetails = function () {
var detail1 = { Description: 'Detail1', MinPercentage: 0, MaxPercentage: 20 }
var detail2 = { Description: 'Detail2', MinPercentage: 40, MaxPercentage: 60 }
var detail3 = { Description: 'Detail3', MinPercentage: 60, MaxPercentage: 72 }
var detail4 = { Description: 'Detail4', MinPercentage: 72, MaxPercentage: 100 }
var detail5 = { Description: 'Detail5', MinPercentage: 20, MaxPercentage: 40 }
return new Array(detail1, detail2, detail3, detail4, detail5);
}
// Performs type checking, logical validation, and requirements validation.
var areIntervalsValid = function (items, min, max, minProperty, maxProperty) {
// Returned object.
var result = {
Success: false,
Message: ''
}
// Checks arguments have expected types.
var validateFunctionCall = function () {
if (!Array.isArray(items) || typeof min !== 'number' || typeof max !== 'number' || typeof minProperty !== 'string' || typeof maxProperty !== 'string')
throw 'An error occurred while processing validation.';
if (!items.length || min > max)
throw 'An error occurred while processing validation.';
}
// Checks [minProperty] of detail that has minimum [minProperty] == min
// and [maxProperty] of detail that has maximum [minProperty]
var validateIntervalBasics = function () {
if (items[0][minProperty] != min || items[items.length - 1][maxProperty] != max)
throw 'Start and end values of interval do not match minimum - maximum values.';
}
// Checks @item has [minProperty] and [maxProperty].
var validateHasProperty = function (item) {
if (!item.hasOwnProperty(minProperty) || !item.hasOwnProperty(maxProperty)) {
throw 'An error occurred while processing validation.';
}
}
try {
validateFunctionCall();
// Sorts array of details in according to [minProperty].
items.sort(function (item1, item2) { return item1[minProperty] > item2[minProperty] });
validateIntervalBasics();
var totalDiff = 0, currentItem;
// Algorithm part.
for (var i = 0; i < items.length; i++) {
currentItem = items[i];
validateHasProperty(currentItem);
totalDiff += currentItem[maxProperty] - currentItem[minProperty];
if (i != items.length - 1 && currentItem[maxProperty] > items[i + 1][minProperty]) { // Finds intersections.
throw "There are intersected values: " + currentItem[maxProperty] + " - " + items[i + 1][minProperty];
}
}
// Checks second validation.
if (totalDiff != max - min) {
throw 'Total interval sum is not equal to ' + (max - min);
}
result.Success = true;
return result;
} catch (e) {
console.log(e);
result.Message = e;
return result;
}
}
然后,我这样调用函数:
areIntervalsValid(getDetails(), 0, 100, "MinPercentage", "MaxPercentage");
如何使函数更可靠、通用和快速?
最佳答案
如果您使用函数式编程原则(尤其是递归),这可以以更好的方式完成。
这个问题有我的解决方案。没有数据类型验证逻辑,因为我相信你可以自己做:
// Numbers and intervals comparison logic
function intervalsIntersect(start1, end1, start2, end2) {
return inBetween(start1, start2, end2) || inBetween(end1, start2, end2);
}
function inBetween(value, start, end){
return Math.max.apply(null, arguments) != value && Math.min.apply(null, arguments) != value;
}
// Validation logic
function getDetailsIntersectionReport(interval1, interval2) {
var comparisonResult = intervalsIntersect(interval1.MinPercentage, interval1.MaxPercentage, interval2.MinPercentage, interval2.MaxPercentage);
return comparisonResult ? ('[' + interval1.Description + ' instersects with ' + interval2.Description + '], ') : '';
}
function compareHeadWithTailFunctionFactory(head, comparatorFunction) {
return function ( previous, item) {
return previous + comparatorFunction(head, item);
}
}
// you have to inject custom comparator function to make this function generic
function validateWithReport(list, comparatorFunction) {
if (list.length <= 1) { // return if there is nothing to compare
return '';
}
var head = list[0];
var tail = list.slice(1);
return tail.reduce(compareHeadWithTailFunctionFactory(head, comparatorFunction),
'' // initial value - empty string
) + validateWithReport(tail, comparatorFunction);
}
function validateIntervals(intervals) {
var result = validateWithReport(intervals, getDetailsIntersectionReport);
if (result.length) {
throw new Error('There are intersecting intervals: ' + result);
}
return true;
}
// Unit test with Jasmine
describe('validation with report', function() {
var intervalsWithoutIntersections = [
{ Description: 'Detail1', MinPercentage: 0, MaxPercentage: 20 },
{ Description: 'Detail2', MinPercentage: 40, MaxPercentage: 60 },
{ Description: 'Detail3', MinPercentage: 60, MaxPercentage: 72 }
];
var intervalsWithIntersections = [
{ Description: 'Detail4', MinPercentage: 0, MaxPercentage: 21 },
{ Description: 'Detail5', MinPercentage: 20, MaxPercentage: 60 },
{ Description: 'Detail6', MinPercentage: 60, MaxPercentage: 72 }
];
it('should report with exception about error', function() {
expect( function() { // wrapping into closure to catch error properly
validateIntervals(intervalsWithIntersections)
}).toThrowError();
});
it('should report validation with true', function() {
expect(validateIntervals(intervalsWithoutIntersections)).toBeTruthy();
});
});
关于javascript - 区间验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31160344/