Javascript Object.keys(arr).reduce() return 最低调
Javascript Object.keys(arr).reduce() return lowest key
我有 3 个不同的测试用例,每个都传递给下面的函数 getEarliest
:
{}
{ '2022-04-29': 1 }
{ '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 }
从每个测试用例中,我想 return 具有最小日期和最大值的 key:value。我的问题是在第三个测试用例中,我得到的是 '2022-04-29': 3
而不是 '2022-04-28': 3
getEarliest = dates => {
return Object.keys(dates).reduce((prev, curr) => {
if (dates[curr] > prev.date) {
return {
val: dates[curr],
date: curr
};
} else {
return prev;
}
}, {
val: 0,
date: null
}); }
预期结果测试用例 1:{ val: 0, date: null }
预期结果测试用例 2:{ val: 1, date: '2022-04-29' }
预期结果测试用例 3:{ val: 3, date: '2022-04-28' }
看起来您只需要 sort
个对象的两个参数:
const test1 = {};
const test2 = { '2022-04-29': 1 };
const test3 = { '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 };
const test4 = { '2022-04-29': 4, '2022-04-28': 4, '2022-04-30': 4, '2022-05-02': 2 };
const getEarliest = (dates) => {
const [date, val] = Object.entries(dates)
.sort(([k1, v1], [k2, v2]) => v2 - v1 || Date.parse(k1) - Date.parse(k2) )
.at(0) ?? [null, 0];
return { val, date };
};
console.log(getEarliest(test1));
console.log(getEarliest(test2));
console.log(getEarliest(test3));
console.log(getEarliest(test4));
.as-console-wrapper {max-height: 100% !important; top: 0}
与reduce
相同的结果:
const test1 = {};
const test2 = { '2022-04-29': 1 };
const test3 = { '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 };
const test4 = { '2022-04-29': 4, '2022-04-28': 4, '2022-04-30': 4, '2022-05-02': 2 };
const getEarliest = (dates) => {
const [date, val] = Object.entries(dates)
.reduce((prev, curr) => (curr[1] - prev[1] || Date.parse(prev[0]) - Date.parse(curr[0])) > 0
? curr
: prev
, [null, 0]);
return { val, date };
};
console.log(getEarliest(test1));
console.log(getEarliest(test2));
console.log(getEarliest(test3));
console.log(getEarliest(test4));
.as-console-wrapper {max-height: 100%!important;top:0 }
在您的代码中 prev.date
值最初为空。所以 reduce()
将始终 return 初始对象。
试试这个代码,它对你有帮助
getEarliest = (dates) => {
if (Object.keys(dates).length > 0) {
let date = Object.keys(dates).reduce((prev, curr) => {
if (prev > curr) {
return curr;
} else {
return prev;
}
});
return {
val: dates[date],
date: date
}
} else {
return {
val: 0, date: null
}
}
}
因为你有2个排序条件,所以它们必须按一定的顺序排列。根据您的示例,我假设订单是:“最大价值”->“最小日期”。然后你的 if
会变成下面这样:
getEarliest = (dates) => {
return Object.keys(dates).reduce(
(prev, curr) => {
if (dates[curr] > prev.val || (dates[curr] === prev.val && curr < prev.date)) {
return {
val: dates[curr],
date: curr,
}
} else {
return prev
}
},
{
val: 0,
date: null,
}
)
}
在第一个语句中,.date
属性 从未定义,因此它应该是 undefined
。 dates
是一个数组而不是对象,所以 dates[curr]
看起来像 dates['2022-04-28']
这没有用。在符号形式前。 array[5]
一个整数作为 .reduce()
的第三个参数的索引放在括号中
if (dates[curr] > prev.date) {...
你得到 "2022-04-29"
的原因是因为数组永远不会改变,你需要使用 .sort()
更简单的方法或 .reduce()
对日期进行实际排序对新手来说复杂。
详情在下面的例子中注释
let A = {};
let B = {
'2022-04-29': 1
};
let C = {
'2022-04-29': 3,
'2022-04-30': 2,
'2022-04-28': 3,
'2022-05-02': 2
};
// Optional utility function
const log = data => console.log(JSON.stringify(data));
/*
Can convert from timestamp to YYYY-MM-DD and vice versa
*/
const dX = (number, string) => {
let D;
if (number) {
let date = new Date(number);
D = ` ${date.getFullYear()}-${("0" + (date.getMonth() + 1)).slice(-2)}-${("0" + date.getDate()).slice(-2)}`;
} else if (string) {
D = Date.parse(string);
} else {
return false;
}
return D;
};
// Pass tS = {...}
const getEarliest = tS => {
// if tS is empty...
if (Object.keys(tS).length === 0) { // Return premade object
return {
val: 0,
date: null
};
}
/*
Object.entries(tS) converts {k: v, k: v,...} into [[k,v], [k,v]...]
*/
/*
.map(([k, v]) exposes key/value
pairs by destructuring [k, v]
*/
/*
.sort(a, b) is referencing each
date key and converting it into
a number (ms since epoch)
*/
let table = Object.entries(tS).map(([k, v]) => [k, v]).sort((a, b) => dX(null, a[0]) - dX(null, b[0]));
let obj = {};
obj.val = table[0][1];
obj.date = table[0][0];
return obj;
};
log(getEarliest(A));
log(getEarliest(B));
log(getEarliest(C));
我有 3 个不同的测试用例,每个都传递给下面的函数 getEarliest
:
{}
{ '2022-04-29': 1 }
{ '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 }
从每个测试用例中,我想 return 具有最小日期和最大值的 key:value。我的问题是在第三个测试用例中,我得到的是 '2022-04-29': 3
而不是 '2022-04-28': 3
getEarliest = dates => {
return Object.keys(dates).reduce((prev, curr) => {
if (dates[curr] > prev.date) {
return {
val: dates[curr],
date: curr
};
} else {
return prev;
}
}, {
val: 0,
date: null
}); }
预期结果测试用例 1:{ val: 0, date: null }
预期结果测试用例 2:{ val: 1, date: '2022-04-29' }
预期结果测试用例 3:{ val: 3, date: '2022-04-28' }
看起来您只需要 sort
个对象的两个参数:
const test1 = {};
const test2 = { '2022-04-29': 1 };
const test3 = { '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 };
const test4 = { '2022-04-29': 4, '2022-04-28': 4, '2022-04-30': 4, '2022-05-02': 2 };
const getEarliest = (dates) => {
const [date, val] = Object.entries(dates)
.sort(([k1, v1], [k2, v2]) => v2 - v1 || Date.parse(k1) - Date.parse(k2) )
.at(0) ?? [null, 0];
return { val, date };
};
console.log(getEarliest(test1));
console.log(getEarliest(test2));
console.log(getEarliest(test3));
console.log(getEarliest(test4));
.as-console-wrapper {max-height: 100% !important; top: 0}
与reduce
相同的结果:
const test1 = {};
const test2 = { '2022-04-29': 1 };
const test3 = { '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 };
const test4 = { '2022-04-29': 4, '2022-04-28': 4, '2022-04-30': 4, '2022-05-02': 2 };
const getEarliest = (dates) => {
const [date, val] = Object.entries(dates)
.reduce((prev, curr) => (curr[1] - prev[1] || Date.parse(prev[0]) - Date.parse(curr[0])) > 0
? curr
: prev
, [null, 0]);
return { val, date };
};
console.log(getEarliest(test1));
console.log(getEarliest(test2));
console.log(getEarliest(test3));
console.log(getEarliest(test4));
.as-console-wrapper {max-height: 100%!important;top:0 }
在您的代码中 prev.date
值最初为空。所以 reduce()
将始终 return 初始对象。
试试这个代码,它对你有帮助
getEarliest = (dates) => {
if (Object.keys(dates).length > 0) {
let date = Object.keys(dates).reduce((prev, curr) => {
if (prev > curr) {
return curr;
} else {
return prev;
}
});
return {
val: dates[date],
date: date
}
} else {
return {
val: 0, date: null
}
}
}
因为你有2个排序条件,所以它们必须按一定的顺序排列。根据您的示例,我假设订单是:“最大价值”->“最小日期”。然后你的 if
会变成下面这样:
getEarliest = (dates) => {
return Object.keys(dates).reduce(
(prev, curr) => {
if (dates[curr] > prev.val || (dates[curr] === prev.val && curr < prev.date)) {
return {
val: dates[curr],
date: curr,
}
} else {
return prev
}
},
{
val: 0,
date: null,
}
)
}
在第一个语句中,
的第三个参数的索引放在括号中.date
属性 从未定义,因此它应该是undefined
。dates
是一个数组而不是对象,所以dates[curr]
看起来像dates['2022-04-28']
这没有用。在符号形式前。array[5]
一个整数作为.reduce()
if (dates[curr] > prev.date) {...
你得到
"2022-04-29"
的原因是因为数组永远不会改变,你需要使用.sort()
更简单的方法或.reduce()
对日期进行实际排序对新手来说复杂。
详情在下面的例子中注释
let A = {};
let B = {
'2022-04-29': 1
};
let C = {
'2022-04-29': 3,
'2022-04-30': 2,
'2022-04-28': 3,
'2022-05-02': 2
};
// Optional utility function
const log = data => console.log(JSON.stringify(data));
/*
Can convert from timestamp to YYYY-MM-DD and vice versa
*/
const dX = (number, string) => {
let D;
if (number) {
let date = new Date(number);
D = ` ${date.getFullYear()}-${("0" + (date.getMonth() + 1)).slice(-2)}-${("0" + date.getDate()).slice(-2)}`;
} else if (string) {
D = Date.parse(string);
} else {
return false;
}
return D;
};
// Pass tS = {...}
const getEarliest = tS => {
// if tS is empty...
if (Object.keys(tS).length === 0) { // Return premade object
return {
val: 0,
date: null
};
}
/*
Object.entries(tS) converts {k: v, k: v,...} into [[k,v], [k,v]...]
*/
/*
.map(([k, v]) exposes key/value
pairs by destructuring [k, v]
*/
/*
.sort(a, b) is referencing each
date key and converting it into
a number (ms since epoch)
*/
let table = Object.entries(tS).map(([k, v]) => [k, v]).sort((a, b) => dX(null, a[0]) - dX(null, b[0]));
let obj = {};
obj.val = table[0][1];
obj.date = table[0][0];
return obj;
};
log(getEarliest(A));
log(getEarliest(B));
log(getEarliest(C));