【问题标题】:Using lodash, why is the map method within flow not working?使用 lodash,为什么流程中的 map 方法不起作用?
【发布时间】:2019-07-04 18:54:33
【问题描述】:

我有一个用户对象,我试图在其上使用 lodash map() 方法让它只返回用户 ID,同时过滤掉任何带有 currentUserId 的用户。我想避免使用chain(),因为它会拉入整个库,所以看起来flow() 方法是完美的,但它没有映射到ID 数组。

import {
  map, filter, flow,
} from 'lodash';

const users = {
    123: {
      uid: 123
    },
    456: {
      uid: 456
    }
};

const currentUserId = 123;

const userIds = _.flow(
  _.map(user => user.uid),
  _.filter(userId => userId !== currentUserId),
)(users);

不幸的是,这将返回与传递给它的对象相同的对象。如何获取包含所有非当前用户的用户 ID 的数组?

【问题讨论】:

  • _.map(user => user.uid) 被评估之前 _.flow() 甚至被调用。
  • @Pointy 这似乎是 lodash 的函数式用法,所以 _.map 不应该是创建一个期望对象执行映射的新函数的柯里化调用吗?除非 OP 没有在其函数形式中使用 lodash,否则 _.map 不应在之后立即执行
  • Lodash 不会(也不能)改变基本的 JavaScript 表达式求值的工作方式。 Lodash _.flow() 方法需要传递一个函数引用数组。这不是在发布的代码中所做的。
  • @Pointy 我没有关注你。您介意用正确编写的代码提供答案吗?
  • _.map(user => user.uid)函数调用,而不是函数。

标签: javascript lodash


【解决方案1】:

答案适用于标准版的 lodash。请参阅@Vlaz 的回答以了解 lodash 的函数式编程版本。


当您编写_.map(user => user.uid) 时,它实际上是在调用该函数。您真正想要做的是创建类似于_.map 的函数,但已经设置了其中一个参数。

幸运的是,Lodash 内置了处理这种情况 - _.partialRight

const userIds = _.flow(
  _.partialRight(_.map, user => user.uid)
  _.partialRight(_.filter, userId => userId !== currentUserId),
)(users);

Documentation


或者,如果您希望使用纯 JS 而不是导入新函数,您可以简单地将其包装在匿名函数中以正确传递参数。

const userIds = _.flow(
  (users) => _.map(users, user => user.uid),
  (users) => _.filter(users, userId => userId !== currentUserId),
)(users);

【讨论】:

  • When you write _.map(user => user.uid) it is actually invoking the function at that time. Here is how _.map doesn't invoke the function.
  • @vlaz 如果 OP 使用的是 lodash 的 FP 版本,我希望他们写的是 import { map, filter, flow } from 'lodash/fp';。我不知道那个变种,但如果他们使用那个库,那么你是对的。我将更新我的答案以声明它适用于标准版本的 lodash
【解决方案2】:

您似乎没有使用functional version of lodash

var users = {
    123: {
      uid: 123
    },
    456: {
      uid: 456
    }
};
var currentUserId = 123;

const userIds = _.flow(
  _.map(user => user.uid),
  _.filter(userId => userId !== currentUserId)
)(users);

console.log("result with normal lodash", userIds);
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>

var users = {
    123: {
      uid: 123
    },
    456: {
      uid: 456
    }
};
var currentUserId = 123;

const userIds = _.flow(
  _.map(user => user.uid),
  _.filter(userId => userId !== currentUserId)
)(users);

console.log("result with lodash FP", userIds);
<script src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>

根据 Lodash FP 指南,您应该将其导入文件中

// Load the fp build.
var fp = require('lodash/fp');

在您的情况下,您可以只导入 mapfilterflow,但您应该获得它们的 lodash FP 变体。

【讨论】:

  • 天哪!我什至不知道 Lodash 的功能版本!这太有用了!谢谢!
  • @Fogmeister 太棒了,我同意。如果需要/需要,您可以手动将函数从“正常”转换为 FP。你必须通过flip/rearg -> curry 传递它们,我认为你可能需要为某些(大多数?)显式设置ary,否则咖喱不知道可选参数的数量。你可以flow所有这些一起。这并不理想,因为您需要转换要使用的每个函数,并且您不妨使用 lodash/fp,但是如果您被“普通” lodash 卡住并且需要某些部分的功能方法。
  • 目前我自己在用partialpartialRight 做所有的fp 工作。现在最好的一点是我可以删除我正在使用的所有那些,而只使用 fp 函数。 :D
【解决方案3】:

可以使用由Object#values() 创建的简单的原生 JS 减少数组来做到这一点,只需要使用 lodash 的代码

const users = {123: {uid: 123},456: {uid: 456}};

const currId = 123;


const userIds = Object.values(users)
            .reduce((a, {uid}) => uid !== currId ? a.concat(uid): a, [])
    

console.log(userIds)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 2017-07-09
    • 2023-03-03
    • 2012-07-30
    • 2016-07-14
    • 1970-01-01
    • 2017-03-21
    相关资源
    最近更新 更多