基于 Array#reduce 如何识别与某些特定约束最匹配的数组项?
Based on Array#reduce how does one identify the array item which matches best some specific constraints?
基本上我要做的是映射这个数组并确定哪些对象满足特定条件。条件是:
获取一个具有最高 a+b 值的对象,如果您有两个具有相同 a+b 值的对象,则获取具有最高 c 值的对象。做这个的最好方式是什么?也许减少?
const data = [
{
id: 1,
a: 12,
b: 75,
c: 11,
},
{
id: 2,
a: 65,
b: 14,
c: 32,
},
{
id: 3,
a: 32,
b: 23,
c: 45,
},
{
id: 4,
a: 22,
b: 1,
c: 3,
},
];
一个简单的 for
循环应该可以工作。遍历数组,如果当前对象的 a
+ b
大于存储的对象,则用当前循环对象覆盖存储的对象 - 如有必要,检查 c
。
第一个基于 reduce
的朴素方法实现了 OP 的要求和约束,几乎完全符合 OP 的要求。
如果不向 reducer 提供 initial value,则此缩减回调函数会在第一次调用时传递前两个数组项。该函数应该 return 一个值,在接下来的任何迭代步骤中,该值将作为函数的第一个参数与当前处理的数组项(即第二个参数)一起传递。
因此,对于 OP 的用例,只需实施正确的比较,始终确保预期的 return 值 ...
function getItemWithHighestTotal(result, item) {
const resultTotal = result.a + result.b;
const itemTotal = item.a + item.b;
return (
((resultTotal > itemTotal) && result) ||
((resultTotal < itemTotal) && item) ||
((result.c < item.c) && item) ||
// OP did not define the clause where
// even both `c` values are equal.
result
);
}
console.log(
[{
id: 1,
a: 12,
b: 75,
c: 11,
}, {
id: 2,
a: 65,
b: 14,
c: 32,
}, {
id: 3,
a: 32,
b: 23,
c: 45,
}, {
id: 4,
a: 22,
b: 1,
c: 3,
}].reduce(getItemWithHighestTotal)
);
console.log(
[{
id: 1,
a: 12,
b: 75,
c: 11,
}, {
id: 2,
a: 65,
b: 14,
c: 32,
}, {
id: 3,
a: 32,
b: 23,
c: 45,
}, {
id: 4,
a: 22,
b: 1,
c: 3,
}, {
id: 5,
a: 75,
b: 12,
c: 12,
}].reduce(getItemWithHighestTotal)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
一个简单的 for 循环会很棒
const data = [
{
id: 1,
a: 12,
b: 75,
c: 11,
},
{
id: 2,
a: 65,
b: 14,
c: 32,
},
{
id: 3,
a: 32,
b: 23,
c: 45,
},
{
id: 4,
a: 22,
b: 1,
c: 3,
},
];
let index,
cHigh = Number.MIN_SAFE_INTEGER,
total = Number.MIN_SAFE_INTEGER;
for (let i = 0; i < data.length; ++i) {
const { a, b, c } = data[i];
if (a + b > total) {
total = a + b;
index = i;
} else if (a + b === total) {
if (c > cHigh) {
cHigh = c;
index = i;
}
}
}
console.log(index);
console.log(data[index]);
data.reduce((res, obj) => {
if (!res) return obj
const { a: resA, b: resB, c: resC } = res
const { a, b, c } = obj
const sumRes = resA + resB
const sum = a + b
if(sum > sumRes) return obj
else if (sum === sumRes) return c > resC ? obj : res
else return res
}, null)
我觉得很好理解。
我们用第一个索引初始化第一个结果。并且我们做了一个简单的比较游戏
如果您愿意,可以使用 Array#reduce
。
下面acc
累加器用来存放当前已知的最大项。 data
中的每个项目都被访问一次,因此时间复杂度为 O(n)
。
如果当前项目curr
的a + b
值与acc
中项目的a + b
值相同,那么我们比较两者的c
值项目,return 具有较大 c
的项目。
如果当前项的a + b
值大于acc
中的值,那么我们returncurr
为acc
下一个要枚举的项目。
否则我们returnacc
(因为curr
一定小于acc
)。
一旦 data
中的项目枚举完成,reduce
将 return acc
的最终值,这将是“最大”的对象。
const data = [
{ id:1, a:12, b:75, c: 11 },
{ id:2, a:65, b:14, c: 32 },
{ id:3, a:32, b:23, c: 45 },
{ id:4, a:22, b:1, c: 3 } ]
const largest = (arr) =>
arr.reduce((acc, curr) => {
switch(Math.sign((curr.a + curr.b) - (acc.a + acc.b))) {
case 0:
return curr.c > acc.c ? curr : acc
case 1:
return curr
default:
return acc
}})
console.log(largest(data))
基本上我要做的是映射这个数组并确定哪些对象满足特定条件。条件是: 获取一个具有最高 a+b 值的对象,如果您有两个具有相同 a+b 值的对象,则获取具有最高 c 值的对象。做这个的最好方式是什么?也许减少?
const data = [
{
id: 1,
a: 12,
b: 75,
c: 11,
},
{
id: 2,
a: 65,
b: 14,
c: 32,
},
{
id: 3,
a: 32,
b: 23,
c: 45,
},
{
id: 4,
a: 22,
b: 1,
c: 3,
},
];
一个简单的 for
循环应该可以工作。遍历数组,如果当前对象的 a
+ b
大于存储的对象,则用当前循环对象覆盖存储的对象 - 如有必要,检查 c
。
第一个基于 reduce
的朴素方法实现了 OP 的要求和约束,几乎完全符合 OP 的要求。
如果不向 reducer 提供 initial value,则此缩减回调函数会在第一次调用时传递前两个数组项。该函数应该 return 一个值,在接下来的任何迭代步骤中,该值将作为函数的第一个参数与当前处理的数组项(即第二个参数)一起传递。
因此,对于 OP 的用例,只需实施正确的比较,始终确保预期的 return 值 ...
function getItemWithHighestTotal(result, item) {
const resultTotal = result.a + result.b;
const itemTotal = item.a + item.b;
return (
((resultTotal > itemTotal) && result) ||
((resultTotal < itemTotal) && item) ||
((result.c < item.c) && item) ||
// OP did not define the clause where
// even both `c` values are equal.
result
);
}
console.log(
[{
id: 1,
a: 12,
b: 75,
c: 11,
}, {
id: 2,
a: 65,
b: 14,
c: 32,
}, {
id: 3,
a: 32,
b: 23,
c: 45,
}, {
id: 4,
a: 22,
b: 1,
c: 3,
}].reduce(getItemWithHighestTotal)
);
console.log(
[{
id: 1,
a: 12,
b: 75,
c: 11,
}, {
id: 2,
a: 65,
b: 14,
c: 32,
}, {
id: 3,
a: 32,
b: 23,
c: 45,
}, {
id: 4,
a: 22,
b: 1,
c: 3,
}, {
id: 5,
a: 75,
b: 12,
c: 12,
}].reduce(getItemWithHighestTotal)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
一个简单的 for 循环会很棒
const data = [
{
id: 1,
a: 12,
b: 75,
c: 11,
},
{
id: 2,
a: 65,
b: 14,
c: 32,
},
{
id: 3,
a: 32,
b: 23,
c: 45,
},
{
id: 4,
a: 22,
b: 1,
c: 3,
},
];
let index,
cHigh = Number.MIN_SAFE_INTEGER,
total = Number.MIN_SAFE_INTEGER;
for (let i = 0; i < data.length; ++i) {
const { a, b, c } = data[i];
if (a + b > total) {
total = a + b;
index = i;
} else if (a + b === total) {
if (c > cHigh) {
cHigh = c;
index = i;
}
}
}
console.log(index);
console.log(data[index]);
data.reduce((res, obj) => {
if (!res) return obj
const { a: resA, b: resB, c: resC } = res
const { a, b, c } = obj
const sumRes = resA + resB
const sum = a + b
if(sum > sumRes) return obj
else if (sum === sumRes) return c > resC ? obj : res
else return res
}, null)
我觉得很好理解。
我们用第一个索引初始化第一个结果。并且我们做了一个简单的比较游戏
如果您愿意,可以使用 Array#reduce
。
下面acc
累加器用来存放当前已知的最大项。 data
中的每个项目都被访问一次,因此时间复杂度为 O(n)
。
如果当前项目curr
的a + b
值与acc
中项目的a + b
值相同,那么我们比较两者的c
值项目,return 具有较大 c
的项目。
如果当前项的a + b
值大于acc
中的值,那么我们returncurr
为acc
下一个要枚举的项目。
否则我们returnacc
(因为curr
一定小于acc
)。
一旦 data
中的项目枚举完成,reduce
将 return acc
的最终值,这将是“最大”的对象。
const data = [
{ id:1, a:12, b:75, c: 11 },
{ id:2, a:65, b:14, c: 32 },
{ id:3, a:32, b:23, c: 45 },
{ id:4, a:22, b:1, c: 3 } ]
const largest = (arr) =>
arr.reduce((acc, curr) => {
switch(Math.sign((curr.a + curr.b) - (acc.a + acc.b))) {
case 0:
return curr.c > acc.c ? curr : acc
case 1:
return curr
default:
return acc
}})
console.log(largest(data))