将_.groupBy传递给_.artialRight似乎给出了不正确的结果

Passing _.groupBy to _.partialRight seems to give incorrect results(将_.groupBy传递给_.artialRight似乎给出了不正确的结果)
本文介绍了将_.groupBy传递给_.artialRight似乎给出了不正确的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有一个JavaScript对象,

const obj = {a: [{ id: 1 }, {id: 1}, {id: 2}, {id: 3}], b: [{ id: 4 }, {id: 5}, {id: 5}, {id: 6}] };

下面的代码按.id对两个数组ojb.aobj.b中的每个数组中的.id正确分组,

const res1 = _.map(obj, x => _.groupBy(x, 'id'));

结果为

[
 {
  1: [{id: 1}, {id: 1}],
  2: [{id: 2}],
  3: [{id: 3}]
 },
 {
  4: [{id: 4}],
  5: [{id: 5}, {id: 5}],
  6: [{id: 6}]
 }
]

但是,lambda实际上只是对其第二个参数_.groupBy的部分应用,该参数设置为'id',所以我认为这样的操作应该可以,

const res2 = _.map(obj, _.partialRight(_.groupBy, 'id'));

或者至少是这样的

const res2 = _.map(obj, _.partialRight(_.groupBy, x => x.id));

但是,它们都不起作用,都会产生此对象:

[
 {
   undefined: [{id: 1}, {id: 1}, {id: 2}, {id: 3}]
 },
 {
   undefined: [{id: 4}, {id: 5}, {id: 5}, {id: 6}]
 }
]

为什么?它是lodash中的错误吗?还是因为JavaScript的工作方式?在后一种情况下,发生了什么情况?


我找到了一个现有的question + self-answer,它提供了使上述代码正常工作的解决方案:

const res2 = _.map(obj, _.ary(_.partialRight(_.groupBy, 'id'), 1));
但是,我的部分问题仍然没有得到回答:为什么我需要使用_.ary?为什么我的初始尝试不起作用?

推荐答案

_.partialRight方法仍然可以接受比新函数应该接受的参数更多的参数。如果一个函数有两个参数,部分应用了一个或两个,那么任何额外的参数都会有效地将部分应用的参数去掉:

function print(a, b) {
  console.log(a, b);
}

const f = _.partialRight(print, "world");
const g = _.partialRight(print, "hello", "world");

f("hi");                    // hi world
g();                        // hello world

f("hi", "universe");        // hi universe
g("greetings");             // greetings world
g("greetings", "universe"); // greetings universe
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

发生这种情况是因为_.partialRight实际上添加到了arguments对象的末尾:

function print(a, b) {
  console.log(...arguments);
}

const f = _.partialRight(print, "world");
const g = _.partialRight(print, "hello", "world");

f("hi");                    // hi world
g();                        // hello world

f("hi", "universe");        // hi universe world
g("greetings");             // greetings hello world
g("greetings", "universe"); // greetings universe hello world
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

因此,_.partialRight构造的函数容易受到the same problem that passing parseInt as callback has的影响-可以传入更多参数,传入,因为_.map的回调总是传递元素、索引和数组。因此,即使_.partialRight(_.groupBy, 'id')应该将第二个参数设置为'id',当_.map作为callback(item, index, array)调用函数时,它会变成第四个参数。实际上,执行的回调是

(item, index, array) => _.groupBy(item, index, array, 'id')

这就是使用_.ary(fn, 1)或直接使用_.unary()来限制arity的原因-在这种情况下,将丢弃_.map()中的额外参数,并且只处理第一个参数:

function print(a, b) {
  console.log(a, b);
}

const f = _.unary(_.partialRight(print, "world"));

f("hi");                    // hi world
f("hi", "universe");        // hi world
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>


对于记录,如果您喜欢更实用的样式和point-free style,那么您可以使用Lodash FPLodash发行版,这会使这一点变得更容易。所有导出的函数都是Currate的,参数也会更改,因此数据始终是最后的。这使您可以更轻松地构建给定数据的处理:

const obj = {a: [{ id: 1 }, {id: 1}, {id: 2}, {id: 3}], b: [{ id: 4 }, {id: 5}, {id: 5}, {id: 6}] };

const process = _.map(_.groupBy("id"));

console.log(process(obj));
.as-console-wrapper { max-height: 100% !important; }
<script src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>

这篇关于将_.groupBy传递给_.artialRight似乎给出了不正确的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)