我正在尝试使用reduce来解决以下问题,但是我无法获得对象中偶数和奇数的正确计数。
有人可以指导我我的代码有什么问题吗?
创建一个函数countBy,它接受一个数组和一个回调,并且 返回一个对象。 countBy将遍历数组并执行 每个元素上的回调。回调中的每个返回值都会 保存为对象上的键。与每个键关联的值 将是返回特定返回值的次数
function countBy(arr, fn) {
return arr.reduce(function(acc, nums) {
// console.log(nums);
let oddCount = 0
let evenCount = 0
console.log(nums, fn(nums))
if(fn(nums) === "even"){
evenCount++;
acc['even'] = evenCount;
} else {
oddCount++;
acc['odd'] = oddCount;
}
return acc
}, {}, 0)
}
function evenOdd(n) {
if (n % 2 === 0) return "even";
else return "odd";
}
var nums = [1, 2, 3, 4, 5];
console.log(countBy(nums, evenOdd)); // should log: { odd: 3, even: 2 }
答案 0 :(得分:3)
您正在将oddCount
的{{1}}和evenCount
初始化为0
的{{1}}内部,因此在每次迭代中,您的
reduce
仅将evenCount++;
acc['even'] = evenCount;
或evenCount
递增到oddCount
。相反,请在回调外部初始化计数,以便对它们的更改在1
回调的多次调用中保持不变:
reduce
或者,通过检查累加器上已经存在的属性的值,您可以完全避免使用外部变量:
function countBy(arr, fn) {
let oddCount = 0
let evenCount = 0
return arr.reduce(function(acc, nums) {
// console.log(nums);
console.log(nums, fn(nums))
if (fn(nums) === "even") {
evenCount++;
acc['even'] = evenCount;
} else {
oddCount++;
acc['odd'] = oddCount;
}
return acc
}, {}, 0)
}
function evenOdd(n) {
if (n % 2 === 0) return "even";
else return "odd";
}
var nums = [1, 2, 3, 4, 5];
console.log(countBy(nums, evenOdd)); // should log: { odd: 3, even: 2 }
答案 1 :(得分:1)
正如SomePerformance所说,您正在重新初始化要用来计数的变量。另外,您还发送了一个额外的参数来减少,该参数不应该存在。 Reduce仅需要2个参数。
这就是我要做的事情
function countBy(arr, fn) {
return arr.reduce(function(acc, nums) {
console.log(nums, fn(nums))
if(fn(nums) === "even"){
acc.even ++;
} else {
acc.odd ++;
}
return acc
}, {odd: 0, even: 0})
}
根据日志,这是按照您想要的方式解决的。如果您要遵循这些命令,我认为它实际上应该是这样的:
function countBy(arr, fn) {
return arr.reduce(function(acc, val) {
let key = fn(nums);
if (!acc[key]) {
acc[key] = 1;
} else {
acc[key]++;
}
return acc;
}, {})
}
您的原始尝试依赖于返回“奇数”或“偶数”才能正常工作的回调函数。上面的代码可以与返回任何值的函数一起使用
答案 2 :(得分:0)
除了使用Array.reduce
以外,您还可以通过Array.forEach
和一个辅助函数来解决此问题:
const isEvenOrOdd = n => n % 2 ? "even" : "odd"
const propCount = (prop, obj) => obj[prop] = (obj[prop] || 0) + 1
const countBy = (arr, fn, obj={}) => {
arr.forEach(x => propCount(isEvenOrOdd(x), obj))
return obj
}
console.log(countBy([1, 2, 3, 4, 5], isEvenOrOdd));
答案 3 :(得分:0)
我将从通用函数开始,该函数用于增加对象k
上的键o
const incr = k => ({ [k]: val = 0, ...o }) =>
({ ...o, [k]: val + 1 })
const incrFoo =
incr ("foo")
console .log
( incrFoo ({})
// { foo: 1 }
, incrFoo ({ bar: 100 })
// { bar: 100, foo: 1 }
, incrFoo ({ foo: 3, bar: 100 })
// { bar: 100, foo: 4 }
, incr ("even") ({ odd: 2, even: 2 })
// { odd: 2, even: 3 }
)
将其插入reduce
,而countBy
基本上会自行写入-
const incr = k => ({ [k]: val = 0, ...o }) =>
({ ...o, [k]: val + 1 })
const countBy = (f, xs = []) =>
xs .reduce
( (acc, x) => incr (f (x)) (acc)
, {}
)
console .log
( countBy
( x => x & 1 ? "odd" : "even"
, [ 1, 2, 3, 4, 5 ]
)
// { even: 2, odd: 3 }
, countBy
( x => x
, [ 'a', 'b', 'b', 'c', 'c', 'c' ]
)
// { a: 1, b: 2, c: 3 }
)
高阶函数不限于map
,filter
和reduce
-使用下面的连续组合器$
,我们将countBy
显示为递归函数。另外一个优点是,该实现接受任何 iterable 作为输入;不仅是数组。
const incr = k => ({ [k]: val = 0, ...o }) =>
({ ...o, [k]: val + 1 })
const $ = x => k =>
k (x)
const None =
Symbol ()
const countBy = (f, [ x = None, ...xs ]) =>
x === None
? {}
: $ (f (x))
(key => $ (countBy (f, xs)) (incr (key)))
console .log
( countBy
( x => x & 1 ? "odd" : "even"
, [ 1, 2, 3, 4, 5 ]
)
// { even: 2, odd: 3 }
, countBy
( x => x
, "mississippi"
)
// { p: 2, s: 4, i: 4, m: 1 }
)
答案 4 :(得分:0)
最简单的方法是创建一个函数来检查偶数,如
const isEven = n => n%2 === 0;
初始化对象的结果应该是这样的
{odd: 0, even: 0}
var nums = [1, 2, 3, 4, 5];
const isEven = n => n%2 == 0;
const result = nums.reduce((acc, curr) => {
if(isEven(curr)) acc.even++;
else acc.odd++;
return acc;
}, {odd: 0, even: 0})
console.log(result); // should log: { odd: 3, even: 2 }