使用JavaScript过滤多个参数?

时间:2017-11-10 05:33:16

标签: javascript functional-programming

我有一个需要过滤的对象数组。

如果对象的活动值为true,则无论其他因素如何,都应始终返回该值。

如果输入了searchText,则应通过此搜索文本过滤列表的其余部分。

如果输入了countrySearch,则应按此值过滤列表,如果提供了该列,则也应过滤searchText。

const searchText = 'Di';
const countrySearch = "USA";

const myArray = [
    {
        name: "Tom",
        country: "UK",
        active: true
    },
    {
        name: "Dick",
        country: "USA",
        active: false
    },
    {
        name: "Dimmon",
        country: "FR",
        active: false
    }
].filter(item => { 
    if (item.active === true) {
        return true;
    }
  if (searchText) {
    if(item.name.includes(searchText)) {
      return true;
    }
  }
});

console.log(myArray);

在此示例中,新数组应包含Tom,因为active为true。它应该包含Dick,因为他通过了searchText和countrySearch测试。 Dimmon不应该在新数组中,因为他只传递了searchText和countrySearch搜索条件中的一个。

我可以使用我当前的方法来解决这个问题,但是使用嵌套的if语句会让它变得混乱。此外,我的搜索条件可能会随着时间的推移而增加。这是函数式编程的好例子吗?

6 个答案:

答案 0 :(得分:1)

以下是使用transducers

执行此操作的另一种方法
  • 可以使用任意数量的过滤器
  • 输入数组只会被遍历一次



const comp = ( f , g ) =>
  x => f ( g ( x ) )
  
const compose = ( ...fs ) =>
  fs.reduce ( comp , x => x )
  
const append = ( xs , x ) =>
  xs.concat ( [ x ] )
  
const transduce = ( ...ts ) => xs =>
  xs.reduce ( ts.reduce ( comp ) ( append ) , [] )
  
const filterer = f =>
  k => ( acc , x ) => f ( x ) ? k ( acc , x ) : acc
  
const search = ( query , country, items ) =>
  transduce ( filterer ( x => x.active === true )
            , filterer ( x => x.name.includes ( query ) )
            , filterer ( x => x.country === country )
            ) (items)

const data0 = 
  [ { name: 'Tom'
    , country: 'UK'
    , active: true
    }
  , { name: 'Dick'
    , country: 'USA'
    , active: true
    }
  , { name: 'Dimmon'
    , country: 'FR'
    , active: false
    }
  ]

            
console.log ( search ( 'Di', 'USA', data0 ) )
// [ { name: 'Dick'
//   , country: 'USA'
//   , active: true
//   }
// ]




如果您不想要通用程序附带的仪式,您可以随时构建完全专有的API



  
const run = ( value = [] ) =>
  ( { type : run
    , value : value
    }
  )

const filterer = f => g =>
  g && g.type === run
    ? g.value.filter ( x => f ( x ) )
    : filterer ( x => f ( x )  && g ( x ) )
    
const search = ( query , country , items ) =>
  filterer ( x => x.active === true )
           ( x => x.name.includes ( query ) )
           ( x => x.country === country )
           ( run ( items ) )

const data0 = 
  [ { name: 'Tom'
    , country: 'UK'
    , active: true
    }
  , { name: 'Dick'
    , country: 'USA'
    , active: true
    }
  , { name: 'Dimmon'
    , country: 'FR'
    , active: false
    }
  ]
            
console.log ( search ( 'Di', 'USA', data0 ) )
// [ { name: 'Dick'
//   , country: 'USA'
//   , active: true
//   }
// ]




答案 1 :(得分:0)

根据您的搜索方法,您可以简化代码,如下所示。

首先使用OR子句搜索连接条件。它只是查看active属性设置为true OR 名称属性包含 Di lexem的对象数组 - 因此所有三个对象都匹配。< / p>

第二个也执行相同的操作,但这次使用 AND 子句,结果为空数组。因为没有任何对象一次处理两个条件。

const searchText = 'Di';
const countrySearch = "USA";

const myArray = [
    {
        name: "Tom",
        country: "UK",
        active: true
    },
    {
        name: "Dick",
        country: "USA",
        active: false
    },
    {
        name: "Dimmon",
        country: "FR",
        active: false
    }
]
console.log('OR')
console.log(myArray.filter(e => e.active || e.name.includes(searchText)));
console.log('AND')
console.log(myArray.filter(e => e.active && e.name.includes(searchText)));

答案 2 :(得分:0)

根据您可以使用active的预期逻辑,OR countrySearch AND countrySearch等于country AND { {1}} searchText AND name .includes()searchText OR searchText AND为{{1} } countrySearch false AND name.includes() searchTextOR searchText false {{ 1}} AND等于countrySearch

&#13;
&#13;
AND
&#13;
&#13;
&#13;

答案 3 :(得分:0)

创建一个函数并传递searchText&amp; countrySearchfilter函数的返回值取决于countrySearch

const searchText = 'Di';
        const countrySearch = "USA";
        const myArray = [
            {
                name: "Tom",
                country: "UK",
                active: true
            },
            {
                name: "Dick",
                country: "USA",
                active: false
            },
            {
                name: "Dimmon",
                country: "FR",
                active: false
            }
        ]
        function getFilterResult(b, c) {
            return myArray.filter(function(a, d) {
           // if countrySearch is undefined then return only active & name
           // which pass the searchText, else return where all the conditions match
                return void 0 === c ? a.active || a.name.includes(b) : 
                a.active || a.name.includes(b) && a.country === c;
            });
        };
    console.log(getFilterResult(searchText,countrySearch));

答案 4 :(得分:0)

<块引用>

在此示例中,新数组应包含 Tom,因为 active 为真。 当他通过 searchText 和 countrySearch 时,它应该包含 Dick 测试。 Dimmon 不应该在新数组中,因为他只传递了 1 个 searchText 和 countrySearch 搜索条件。

const searchText = 'Di';
const countrySearch = "USA";

const myArray = [
{
    name: "Tom",
    country: "UK",
    active: true
},{
    name: "Dick",
    country: "USA",
    active: false
},{
    name: "Dimmon",
    country: "FR",
    active: false
}
].filter(item => item.active || (item.name.includes(searchText)
  && item.country.valueOf() === countrySearch.valueOf() ));
document.write(JSON.stringify(myArray));

答案 5 :(得分:-1)

尝试:

.filter(item => { 
    if (
            (item.active === true) ||
            (searchText && item.name.includes(searchText))
    ) {
        return true;
    }
  }
})