3

我有一个商店列表和一个 ID 列表:

var stores = [{id: '1', name: 'first store'}, {id: '2', name: 'second store'}, {id: '3', name: 'third store'}];
var ids = ['1', '2'];

我想获取与列表中的 id 匹配的商店名称:

["first store", "second store"]

这是我想出的:

var filterStoresById = R.intersectionWith(R.useWith(R.equals, R.view(R.lensProp('id'))));
var extractNames =  R.map(R.view(R.lensProp('name')));
extractNames(filterStoresById(stores,ids));

我的目标是学习函数式编程概念,同时生成可以在现实生活中使用的代码,但我认为我的解决方案既不可读也不高性能(我正在迭代两次),所以可以对此进行哪些改进代码?

4

2 回答 2

3

你的代码并不可怕,只是比它可能的可读性差了一点。

首先,要访问顶级属性,尤其是当您不重用访问方法时,它的使用prop(name)view(lensProp(name)). Ramdapluckmap(prop).

其次,我发现通过函数组合构建的函数比通过嵌套级别的括号更容易阅读。我通常更喜欢pipecompose但两者都可以。

所以我会像这样重写你的代码:

var filterStoresById = R.intersectionWith(R.useWith(R.equals, R.prop('id')));
var storeNamesById = R.pipe(filterStoresById, R.pluck('name'));

storeNamesById(stores, ids);

这样做的一个好处是,filterStoresById如果您发现您需要的不仅仅是名称,那么您现在就有了可重用的功能。

另一个问题是性能问题。迭代两次肯定会受到惩罚。问题是是否值得为更清洁、更容易重构的代码。有一些技术可以将这样的代码转换为执行相同操作但只迭代一次并避免中间容器的代码。您可以查看有关传感器的这些 文章 以获取更多信息。

但我会避免担心这一点,除非您可以向自己证明这实际上是您的应用程序中的一个性能问题。我想每个人都知道 Knuth 的错误引用“过早的优化是万恶之源”。

于 2015-09-15T14:57:37.023 回答
1

内部加入 FTW

const stores = [
  {id: '1', name: 'first store'}, 
  {id: '2', name: 'second store'}, 
  {id: '3', name: 'third store'},
]

const ids = ['1', '2']

const f = 
    R.pipe(R.innerJoin(R.flip(R.propEq('id'))), R.pluck('name'))

console.log(f(stores, ids))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

于 2019-04-10T23:02:17.097 回答