在给定数组

时间:2017-03-28 03:38:14

标签: javascript functional-programming lodash ramda.js

我有一组键值对象,如下所示:

var d = [{'name':'a', 'value':1}, {'name':'b', 'value':2}, {'name':'c', 'value':3}, {'name':'d', 'value':4}, {'name':'e', 'value':5}, {'name':'f', 'value':6}]

和一个数组

var a = ['a','e']

如何编写一个提取值的函数,基本上是我想要的结果

[{'name':'a', 'value':1},{'name':'e', 'value':5} ]

我想以纯粹的功能方式编写它,而不是使用forwhile循环或filter函数。我想知道有没有一种正确有效的方法?以正确的方式递归?我愿意使用lodashramda或任何其他FP包。

5 个答案:

答案 0 :(得分:5)

Array.prototype.map和Array.prototype.find

您似乎对实施细节感到顽固,但我确定您不知道为什么。 forwhilefilter没有任何问题。在这篇文章的最后,我不希望你相信我,而是希望你知道这是真。

您可以使用mapfind轻松解决此问题 - 出于所有意图和目的, mapfind的实施方式是对你来说很神秘。如果他们使用for循环甚至是GOTO来大声哭泣并不重要。对您而言重要的是您能够以功能性的方式表达您的问题。

mapfind是简单的JavaScript函数程序员的完美伴侣......



var d = [{'name':'a', 'value':1}, {'name':'b', 'value':2}, {'name':'c', 'value':3}, {'name':'d', 'value':4}, {'name':'e', 'value':5}, {'name':'f', 'value':6}]

var a = ['a','e']

var result = a.map(x => d.find(y => y.name === x))

console.log(result)
// [ { name: 'a', value: 1 },
//   { name: 'e', value: 5 } ]




通用功能促进代码重用

使用一些通用函数,我们可以稍微更加可重用的方式表达解决方案



var data = [{'name':'a', 'value':1}, {'name':'b', 'value':2}, {'name':'c', 'value':3}, {'name':'d', 'value':4}, {'name':'e', 'value':5}, {'name':'f', 'value':6}]

const findBy = k => xs => v =>
  xs.find(x => x[k] === v)

const findAllBy = k => xs => vs =>
  vs.map(findBy(k)(xs))

console.log(findAllBy ('name') (data) (['a', 'e']))
// [ { name: 'a', value: 1 },
//   { name: 'e', value: 5 } ]




为什么顽固不帮助

如果您想要了解如何完成此操作,而不依赖于任何 forwhilefiltermap或{{ 1}} ...



find




非常痛苦啊?并且该代码比其他答案更少,仍然具有var data = [{'name':'a', 'value':1}, {'name':'b', 'value':2}, {'name':'c', 'value':3}, {'name':'d', 'value':4}, {'name':'e', 'value':5}, {'name':'f', 'value':6}] const main = ([x,...xs]) => { const aux = ([y,...ys]) => { if (y === undefined) return null else if (y.name === x) return y else return aux (ys) } if (x === undefined) return [] else return [aux(data), ...main(xs)] } console.log(main(['a', 'e'])) // [ { name: 'a', value: 1 }, // { name: 'e', value: 5 } ]lengthindexOf或整个lodash lib等依赖项。

所以真的没有意义这样做。在这个例子中编码了大量有用的泛型函数,我们希望在其他地方使用它们。这就是为什么slicemapreducefilter等函数首先存在的原因 - 同样适用于find和{{for 1}}。

每次我想循环一个数组,过滤数组,或者在数组中找到一个元素时,我都不想手工完成。我使用函数的原因是我不必重复自己......永远。

<强>好奇心

所以也许您可以使用上面的while + map解决方案,但是您也很好奇如果您没有&#自己如何实施它们&#? 39;已经掌握了它们 - 下面只有2种无数方式可以实现这些功能。

&#13;
&#13;
find
&#13;
&#13;
&#13;

递归在JavaScript中很糟糕

许多人不了解JavaScript中的递归,实际上并不是很好。我们在ES6中得到了尾部调用消除的承诺,但目前没有JavaScript的实现支持它。这意味着您编写的任何递归函数(除非您蹦蹦跳跳)都存在堆栈溢出的潜在风险。

这意味着实现var data = [{'name':'a', 'value':1}, {'name':'b', 'value':2}, {'name':'c', 'value':3}, {'name':'d', 'value':4}, {'name':'e', 'value':5}, {'name':'f', 'value':6}] const find = f => ([x,...xs]) => x === undefined ? null : f(x) === true ? x : find (f) (xs) const map = f => ([x,...xs]) => x === undefined ? [] : [f(x), ...map(f)(xs)] const main = map (x => find (y => y.name === x) (data)) console.log(main(['a', 'e'])) // [ { name: 'a', value: 1 }, // { name: 'e', value: 5 } ]for的功能接口所以更好。

下面,我们重新实现whilemap,但这次我们通过避免堆栈溢出的风险以聪明的方式完成。请注意,它对结果代码没有任何影响。我们仍然可以通过良好,实用的方式与findmap进行互动 - 而且它们都是引用透明的

特别注意find功能 - 它根本没有改变上面的例子。我们的丑陋&#34; mainwhile循环被巧妙地隐藏起来作为实现细节,最终用户不是更明智的。

&#13;
&#13;
for
&#13;
&#13;
&#13;

答案 1 :(得分:2)

var d = [{'name':'a', 'value':1}, {'name':'b', 'value':2}, {'name':'c', 'value':3}, {'name':'d', 'value':4}, {'name':'e', 'value':5}, {'name':'f', 'value':6}];
var a = ['a','e'];

d.filter(function(item){
  return a.indexOf(item.name) > -1; 
})

// will return [{'name':'a', 'value':1}, {'name':'b', 'value':5}]

希望这会有所帮助

答案 2 :(得分:1)

不幸的是,我必须使用R.map,但使用Ramda

R.flatten(R.map(R.useWith(R.filter, [R.propEq('name'), R.identity])(R.__, d), a))

这是我能想到的,但我知道有更好的解决方案,我很乐意听到

编辑:我认为这个更好

R.filter(R.compose(R.flip(R.contains)(a), R.prop('name')), d)

答案 3 :(得分:0)

如果您希望您的解决方案是递归的,那么您需要这样的东西。

function getValues(objects, names, result) {
  if (objects.length === 0 || names.length === 0) {
    return result;
  }
  var index = names.indexOf(objects[0].name)
  if (index > -1) {
    result.push(objects[0]);
    return getValues(objects.slice(1), [...names.slice(0, index), ...names.slice(index, names.length)], result);

  } else {
    return getValues(objects.slice(1), names, result);
  }
}

var d = [{'name':'a', 'value':1}, {'name':'b', 'value':2}, {'name':'c', 'value':3}, {'name':'d', 'value':4}, {'name':'e', 'value':5}, {'name':'f', 'value':6}]

var a = ['a','e']

console.log(getValues(d, a, []));

答案 4 :(得分:-1)

我认为OP正在寻找类似的东西:

const _ = require('lodash');

function solve(array, keys) {
    if (_.isEmpty(array) || _.isEmpty(keys)) {
        return [];
    } else {
        const [ele, ...tailArray] = array;
        const [key, ...tailKeys] = keys;

        if (ele.name === key) {
            return [ele, ...solve(tailArray, tailKeys)];
        } else {
            return solve(tailArray, keys);
        }
    }
}

const d = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}, {'name': 'c', 'value': 3}, {'name': 'd', 'value': 4}, {'name': 'e', 'value': 5}];
const a = ['a', 'e'];

console.log(solve(d, a));

这假定两个数组都已排序,所有名称都是唯一的,array a中的所有元素也存在于array d中。其他解决方案留给了@cherhan。