简体   繁体   English

使用 Ramda 基于多个条件过滤列表

[英]Filter list based on multiple criteria with Ramda

I have a list of cars, that I want to filter based on a filter object, the cars:我有一个汽车列表,我想根据过滤器 object 进行过滤,这些汽车:

const cars = [
    {original: {"make": "audi", "model": "a4"}},
    {original: {"make": "bmw", "model": "m5"}},
    {original: {"make": "mercedes", "model": "s"}},
    {original: {"make": "audi", "model": "a6"}},
];

The filter object, that can have multiple criteria for the same property (these should be considered as OR filters).过滤器 object,可以对同一属性有多个条件(这些应被视为OR过滤器)。 Each entry in this dictionary ("make", "model") should be considered as an AND filter.此字典中的每个条目(“make”、“model”)都应被视为AND过滤器。

const filterObject = {
    "make": {
        filters: [
            {prop: "make", value: "audi"},
            {prop: "make", value: "bmw"}
        ]
    }, 
    "model": {
        filters: [
            {prop: "model", value: "a6"}
        ]
    }
}

So in this case I should get back the audi - a6 .所以在这种情况下,我应该取回audi - a6 With ramda I could get this far:使用 ramda 我可以做到这一点:

filter(
  where({
      make: equals("audi"),
      model: equals("a6")
  }), 
  map(x => x.original, data)
)

Which works, but there are a couple of problems:哪个有效,但有几个问题:

  1. filterObject is assembled dynamically, so I don't know beforehand what properties are filtered. filterObject是动态组装的,所以事先不知道过滤了哪些属性。 I should somehow map the object inside where , but I got stuck with the multiple conditions criteria.我应该以某种方式 map object 里面where ,但我遇到了多个条件标准。 How to make where be aware of multiple predicates for each property?如何让where知道每个属性的多个谓词?
  2. At the end I should get back the original (filtered) array.最后我应该取回原始(过滤的)数组。 But the relevant part is hidden inside a property ( original ), so before I start filtering, I map over the array to supply the relevant part to the where function, therefore in the end this mapped array is returned.但是相关部分隐藏在一个属性( original )中,所以在开始过滤之前,我通过数组 map 将相关部分提供给 function 的where ,因此最终返回这个映射数组。

Maybe where is not the right approach here?也许where没有正确的方法?

R.where expects a an object with a predicate function for each property you wish to test. R.where 期望 object 带有谓词 function 用于您要测试的每个属性。 To pass a tested object needs to satisfy all predicates (and).要通过经过测试的 object 需要满足所有谓词(和)。

To test the current object's make lets say "audi` against an array of options (or), you can use R.includes.要测试当前对象的make让我们针对一组选项(或)说“audi”,您可以使用 R.includes。

So the first step is to create a where object, where each predicate checks the current object's value against an array of values.所以第一步是创建一个where object,其中每个谓词检查当前对象的值与一个值数组。

 const { map, pipe, prop, pluck, includes, flip, where } = R; const createFilters = map(pipe( prop('filters'), pluck('value'), flip(includes) )); const cars = [{"original":{"make":"audi","model":"a4"}},{"original":{"make":"bmw","model":"m5"}},{"original":{"make":"mercedes","model":"s"}},{"original":{"make":"audi","model":"a6"}}]; const filterObject = {"make":{"filters":[{"prop":"make","value":"audi"},{"prop":"make","value":"bmw"}]},"model":{"filters":[{"prop":"model","value":"a6"}]}}; const filters = createFilters(filterObject); console.log(filters); console.log(where(filters, {"make":"audi","model":"a4"})) // false console.log(where(filters, {"make":"audi","model":"a6"})) // true
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous"></script>

Then you when filtering the data, get the object from the origin , and use the R.where with the applied filters:然后在过滤数据时,从origin获取 object ,并使用 R.where 和应用的过滤器:

 const { map, pipe, prop, pluck, includes, flip, curry, filter, where } = R; const createFilters = map(pipe( prop('filters'), pluck('value'), flip(includes) )); const fn = curry((filters, data) => filter(pipe( prop('original'), where(createFilters(filters)), ))(data)); const cars = [{"original":{"make":"audi","model":"a4"}},{"original":{"make":"bmw","model":"m5"}},{"original":{"make":"mercedes","model":"s"}},{"original":{"make":"audi","model":"a6"}}]; const filterObject = {"make":{"filters":[{"prop":"make","value":"audi"},{"prop":"make","value":"bmw"}]},"model":{"filters":[{"prop":"model","value":"a6"}]}}; const result = fn(filterObject)(cars); console.log(result);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM