【问题标题】:More elegant way to get filtered value?更优雅的方式来获得过滤值?
【发布时间】:2016-10-08 14:51:25
【问题描述】:

我有一个函数可以根据对象中的字符串返回过滤结果(如果存在与否)

let foo = nodes.reduce((arr, cur) => {
    cur.classes.split(' ').filter((el) => {
        if (el === 'foo') arr.push(cur)
    })
    return arr; 
}, []);

所以它只是返回数组中包含类对象中'foo'的所有对象 比如这个:

let nodes = [
  {node: 'h1', classes: 'foo'},
  {node: 'p', classes: 'bar'},
  {node: 'p', classes: 'baz xxx'},
  {node: 'h2', classes: 'bar baz foo'},
  {node: 'ul', classes: 'poop foo'}
]

但我的直觉告诉我,这个函数可以写得更简单、更简洁。有什么想法吗?

【问题讨论】:

    标签: javascript arrays object functional-programming


    【解决方案1】:

    你可以只使用Array#filter

    let nodes = [{node: 'h1', classes: 'foo'}, {node: 'p', classes: 'bar'}, {node: 'p', classes: 'baz xxx'}, {node: 'h2', classes: 'bar baz foo'}, {node: 'ul', classes: 'poop foo'}],
        foo = nodes.filter(a => a.classes.split(' ').some(b => b === 'foo'));
    
    console.log(foo);

    【讨论】:

      【解决方案2】:

      与往常一样,@NinaScholz 提供了一种出色而直接的方法。听从她的建议,你会过得很好。

      我个人喜欢进一步剖析这些问题,并演示如何组合更小的、可重用的函数来达到预期的效果。我希望这个答案能帮助您了解 JavaScript 中的函数式编程很容易扩展到内置的原型方法之外。

      注释可帮助您理解类型,但完全是可选的。

      // comp :: (b -> c) -> (a -> b) -> (a -> c)
      const comp = f => g => x => f (g (x));
      
      // filter :: (a -> Boolean) -> [a] -> [a]
      const filter = f => xs => xs.filter(f);
      
      // some :: (a -> Boolean) -> [a] -> Boolean
      const some = f => xs => xs.some(f);
      
      // eq :: (String a, Number a) => a -> a -> Boolean 
      const eq = x => y => y === x;
      
      // nodeClasses :: Node -> [String]
      const nodeClasses = ({classes}) => classes.split(' ');
      
      // nodesWithClass :: String -> [Node] -> [Node]
      const nodesWithClass = c => filter (comp (some (eq (c))) (nodeClasses));
      
      // nodes :: [Node]
      let nodes = [
        {node: 'h1', classes: 'foo'},
        {node: 'p', classes: 'bar'},
        {node: 'p', classes: 'baz xxx'},
        {node: 'h2', classes: 'bar baz foo'},
        {node: 'ul', classes: 'poop foo'}
      ];
      
      console.log(nodesWithClass('foo') (nodes));

      【讨论】:

      • @NinaScholz,我在回答中称您为女性,但我无意做出任何冒犯性的假设。如有错误请指正^_^
      【解决方案3】:

      作为“过滤某些”的替代方案,如 Nina 所示,这是一种略有不同的方法。

      看起来不那么干净,但性能更高(就这样一个简单任务的性能而言)。

      let nodes = [
        {node: 'h1', classes: 'foo'},
        {node: 'p', classes: 'bar'},
        {node: 'p', classes: 'foo-bar'},
        {node: 'p', classes: 'baz xxx'},
        {node: 'h2', classes: 'bar baz foo'},
        {node: 'ul', classes: 'poop foo'}
      ];
      
      let foo = nodes.filter(node => (' ' + node.classes + ' ').contains(' foo '));
      

      【讨论】:

      • 也是不错的解决方案,谢谢托马斯。我会保存它。 :)
      猜你喜欢
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 2014-06-13
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多