使用 Ramda 基于多个条件过滤列表
Filter list based on multiple criteria with Ramda
我有一个汽车列表,我想根据过滤器对象进行过滤,汽车:
const cars = [
{original: {"make": "audi", "model": "a4"}},
{original: {"make": "bmw", "model": "m5"}},
{original: {"make": "mercedes", "model": "s"}},
{original: {"make": "audi", "model": "a6"}},
];
过滤器对象,可以为相同的 属性 设置多个条件(这些应该被视为 OR 过滤器)。此词典中的每个条目(“make”、“model”)都应被视为 AND 过滤器。
const filterObject = {
"make": {
filters: [
{prop: "make", value: "audi"},
{prop: "make", value: "bmw"}
]
},
"model": {
filters: [
{prop: "model", value: "a6"}
]
}
}
所以在这种情况下我应该取回 audi - a6
。
使用 ramda,我可以做到这一点:
filter(
where({
make: equals("audi"),
model: equals("a6")
}),
map(x => x.original, data)
)
哪个有效,但有几个问题:
filterObject
是动态拼装的,所以我事先不知道过滤了哪些属性。我应该以某种方式将对象映射到 where
内,但我遇到了多个条件标准。如何让 where
知道每个 属性 的多个谓词?
- 最后我应该取回原始(过滤后的)数组。但是相关部分隐藏在 属性 (
original
) 中,所以在我开始过滤之前,我映射数组以将相关部分提供给 where
函数,因此最后返回此映射数组。
也许 where
不是正确的方法?
R.where 需要一个对象,其中包含您希望测试的每个 属性 的谓词函数。要通过测试对象需要满足所有谓词(和)。
要测试当前对象的 make
让我们说“audi` 针对选项数组 (or),您可以使用 R.includes.
所以第一步是创建一个 where 对象,其中每个谓词根据值数组检查当前对象的值。
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>
然后您在过滤数据时,从 origin
中获取对象,然后将 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>
我有一个汽车列表,我想根据过滤器对象进行过滤,汽车:
const cars = [
{original: {"make": "audi", "model": "a4"}},
{original: {"make": "bmw", "model": "m5"}},
{original: {"make": "mercedes", "model": "s"}},
{original: {"make": "audi", "model": "a6"}},
];
过滤器对象,可以为相同的 属性 设置多个条件(这些应该被视为 OR 过滤器)。此词典中的每个条目(“make”、“model”)都应被视为 AND 过滤器。
const filterObject = {
"make": {
filters: [
{prop: "make", value: "audi"},
{prop: "make", value: "bmw"}
]
},
"model": {
filters: [
{prop: "model", value: "a6"}
]
}
}
所以在这种情况下我应该取回 audi - a6
。
使用 ramda,我可以做到这一点:
filter(
where({
make: equals("audi"),
model: equals("a6")
}),
map(x => x.original, data)
)
哪个有效,但有几个问题:
filterObject
是动态拼装的,所以我事先不知道过滤了哪些属性。我应该以某种方式将对象映射到where
内,但我遇到了多个条件标准。如何让where
知道每个 属性 的多个谓词?- 最后我应该取回原始(过滤后的)数组。但是相关部分隐藏在 属性 (
original
) 中,所以在我开始过滤之前,我映射数组以将相关部分提供给where
函数,因此最后返回此映射数组。
也许 where
不是正确的方法?
R.where 需要一个对象,其中包含您希望测试的每个 属性 的谓词函数。要通过测试对象需要满足所有谓词(和)。
要测试当前对象的 make
让我们说“audi` 针对选项数组 (or),您可以使用 R.includes.
所以第一步是创建一个 where 对象,其中每个谓词根据值数组检查当前对象的值。
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>
然后您在过滤数据时,从 origin
中获取对象,然后将 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>