JavaScript中的SUM-IFS
如何基于多个真条件的一致性实现求和逻辑,即: 我有一个输入数组: 价值:JavaScript中的SUM-IFS,javascript,Javascript,如何基于多个真条件的一致性实现求和逻辑,即: 我有一个输入数组: 价值:[[dec','toy',12/4/2020,50],'dec','pen',14/4/2020,50],'dec','toy',14/4/2020,53],'dec','toy',4/4/2020,50],] 标题:['month'、'object'、'day'、'score'] 现在我有了一个函数,它包含4个参数: 标题数组 值数组 条件字符串 函数sumif(summationMetricHeader、header、v
[[dec','toy',12/4/2020,50],'dec','pen',14/4/2020,50],'dec','toy',14/4/2020,53],'dec','toy',4/4/2020,50],]
标题:['month'、'object'、'day'、'score']
现在我有了一个函数,它包含4个参数:
函数sumif(summationMetricHeader、header、value、condition)
其中,条件
字符串如下:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
其中@@是指定4个比较参数的分隔符,是多个条件之间的分隔符
如果所有条件均为真,则应添加总和水头
例如:
价值:[[dec','toy',12/4/2020,50],'dec','pen',14/4/2020,50],'dec','toy',14/4/2020,53],'dec','toy',4/4/2020,50],]
标题:['month'、'object'、'day'、'score']
总和指标:得分
条件字符串:12/4/2020@>=@@Date@@day,50@>=@@Number@@score
现在,只有当day列大于等于2020年12月4日时,这里才显示sum(比较必须是指定的日期比较),并且当score大于等于50时(这里的比较是数字类型)
因此,输出将为:50+50+53(对于values数组中的最后一个元素,day列的值小于指定的条件)
总共有三种比较:
let decision = true;
if(stringElem.split("@@")[2] === 'Date')
decision = decision && eval(`${new Date(stringElem.split("@@")[0]).getTime()}${stringElem.split("@@")[1]}${new Date(value[i]).getTime()}`)
else if(stringElem.split("@@")[2] === 'String')
decision = decision && eval(`'${stringElem.split("@@")[0]}'${stringElem.split("@@)[1]}'${value[i]}'`)
日期
串
数
比较:
let decision = true;
if(stringElem.split("@@")[2] === 'Date')
decision = decision && eval(`${new Date(stringElem.split("@@")[0]).getTime()}${stringElem.split("@@")[1]}${new Date(value[i]).getTime()}`)
else if(stringElem.split("@@")[2] === 'String')
decision = decision && eval(`'${stringElem.split("@@")[0]}'${stringElem.split("@@)[1]}'${value[i]}'`)
我尝试使用eval,但无法正确格式化字符串进行比较。谁能帮我解决这个问题?我对Javascript数组方法不是很深入,我想知道是否有更简单的方法来编写相同的代码
下面是我试图实现的函数的一个非常简单的版本:
function computeMetricwithConditions() {
const headers = ['name', 'place','stats', 'score', 'date'];
const data = [['o','b', 22, 2, '4/14/2021']];
const conditions = [['o', '===','String','name'],
['b', '===','String','place'],
['4/14/2021','>=','Date','date'],
[2,'>=','Number','stats']];
const hashMap = {};
headers.forEach((element,index)=> {
hashMap[element] = index;
});
console.log(hashMap);
data.forEach(element => {
let dec = true;
conditions.forEach(elem => {
let comparisionValue = elem[0];
let comparisionOperator = elem[1];
let comparisionType = elem[2];
let comparisionHeader = elem[3];
if(comparisionType === 'String')
{dec = dec && eval(`'${comparisionValue}'${comparisionOperator}'${element[hashMap[comparisionHeader]]}'`);
//console.log(`'${comparisionValue}'${comparisionOperator}'${element[hashMap[comparisionHeader]]}'`);
}
else if(comparisionType === 'Date')
{
dec = dec && eval(`${new Date(comparisionValue).getTime()}${comparisionOperator}${new Date(element[hashMap[comparisionHeader]]).getTime()}`);
}
else
{
dec = dec && eval(`${comparisionValue}${comparisionOperator}${element[hashMap[comparisionHeader]]}`);
}
console.log(dec);
});
});
}
这是我的实现,不确定这是否是一种骇人的方式来完成事情,或者是否有更好的方式来完成同样的事情
用于日期比较。不知道为什么会发生这种情况。我解决这个问题的方法是:
function computeMetricwithConditions() {
const headers = ['name', 'place', 'stats', 'score', 'date'];
const data = [['o','b', 22, 2, '4/14/2021']];
const conditions = [['o', '===','String','name'],['b', '===','String','place'],['4/14/2021','>=','Date','date']];
const hashMap = {};
headers.forEach((element,index)=> {
hashMap[element] = index;
});
data.forEach(element => {
conditions.forEach(elem => {
let op;
switch (elem[1]) {
case '===':
op = (lhs, rhs) => lhs === rhs;
break;
case '>=':
op = (lhs, rhs) => lhs >= rhs;
break;
}
let index = headers.indexOf(elem[3]);
switch (elem[2]) {
case 'String':
console.log(op(toString(elem[0]), toString(element[index])));
break;
case 'Date':
let date1 = elem[0].split('/');
let date2 = element[index].split('/');
console.log(op((new Date(date1[2], date1[0] - 1, date1[1])).getTime(), (new Date(date2[2], date2[0] - 1, date2[1])).getTime()));
break;
}
});
});
}
computeMetricwithConditions();
我会为不同的运算符和类型使用开关。您可以为运算符使用对象,并使用闭包数组来检查值
const
sumif=(summationMetricHeader、标头、值、条件)=>{
常数
headers=Object.fromEntries(header.map((k,v)=>[k,v]),
运算符={
“>=”:(a,b)=>a>=b,
“+”:(a,b)=>a+b
},
类型={
日期:(…a)=>a.map(getISODate),
编号:(a,b)=>[+a,b],
字符串:(…a)=>a,
},
getISODate=string=>string.replace(/(\d+)\/(\d+)\/(\d+)/,(\ux,d,m,y)=>`${y.padStart(4,0)}-${m.padStart(2,0)}-${d.padStart(2,0)}`,
条件
.split(“,”)
.map(s=>s.split('@'))
.map(([left,op,type,column])=>row=>operators[op](…types[type](left,row[headers[column]]));
返回值
.filter(行=>conditions.every(fn=>fn(行)))
.map(行=>行[Header[summationMetricHeader]]
.reduce(运算符['+'],0);
},
标题=[“月”、“对象”、“日”、“分数”],
数值=['dec','toy','12/4/2020',50],'dec','pen','14/4/2020',50],'dec','toy','14/4/2020',53],'dec','toy','4/4/2020',50],
结果=sumif('score',header,value,'12/4/2020@>=@@Date@@day,50@>=@@Number@@score');
控制台日志(结果)代码>您是在询问黑客解决方案还是正确的解决方案?使用eval
没有正确的解决方案。我要求的是正确的解决方案,如果使用eval
没有正确的解决方案,那么最好的方法是什么?日期是标题中的第四个元素,但是数据中的第四个元素是2
。对于所有可能的操作员,我都会使用带有外壳的开关。正如我所说,有一种使用eval
的黑客方法,也有一种不使用eval
的正确方法eval
将是我在所有公司工作过的时候送你回家面试的一个理由。您不应该在生产代码中使用它,最好甚至不知道它。静态代码分析器通常禁止使用它。