【发布时间】:2021-07-07 16:52:42
【问题描述】:
我有 2 个不同的 API。第一个返回一个事件对象数组(这个数据集正在增长并且预计会很大)。每个事件都有一个包含字符串列表的类别数组。另一个 API 返回一个过滤器对象数组。每个过滤器都有一个“名称”属性和一组关键字。在任何情况下,类别数组中包含的任何关键字都应位于此过滤器名称下。 最终目标是在屏幕上显示过滤器列表,当用户单击过滤器时,我应该在此过滤器下呈现所有事件。
事件对象示例:
{
"text": {
"headline": "Headline example",
"text": "event description "
},
"media": {
"url": "https://www.google.com/",
"caption": "",
"credit": ""
},
"categories": [
"National",
"Canada",
"British Columbia"
]
}
过滤器对象示例:
{
"filters": [
{
"keywords": [
"Atlantic",
"New Brunswick",
"Newfoundland and Labrador",
"Prince Edward Island",
"Nova Scotia"
],
"name": "Atlantic"
},
{
"keywords": [
"ontario",
"Quebec"
],
"name": "Central Canada"
},
{
"keywords": [
"Manitoba",
"Saskatchewan",
"Alberta"
],
"name": "Prairie Provinces"
},
{
"keywords": [
"British Columbia"
],
"name": "West Coast"
},
{
"keywords": [
"Nunavut",
"Northwest Territories",
"Yukon Territory"
],
"name": "North"
},
{
"keywords": [
"National"
],
"name": "National"
}
]
}
经过几天的努力,我想出了这个解决方案。
function filterTimelineData(filtersObj, timelineData) {
if (!timelineData || !filtersObj) return [];
// create a new object with filters "name" as key;
const filters = Object.keys(filtersObj);
const filteredTimelineData = Object.keys(filtersObj).reduce((o, key) => ({ ...o, [key]: [] }), {});
const filteredData = timelineData.events.reduce((acc, current) => {
let filterMatch = false;
let filterMatchName = '';
for (let i = 0; i < filters.length; i++) {
filterMatch = current.categories.some(item => {
return filtersObj[filters[i]].includes(item.toLocaleLowerCase());
});
if (filterMatch && filterMatchName !== filters[i]) { // to avoid duplicated items with different categories under the same filter
filterMatchName = filters[i];
acc[filters[i]].push(current);
}
}
return acc;
}, filteredTimelineData);
return filteredData;
}
export function timelineFiltersObj(filters) {
const filtersObj = filters.filters.reduce((acc, current) => {
const filterName = current.name.replace(/ /g, '_').toLocaleLowerCase();
if (!acc.hasOwnProperty(filterName)) {
acc[filterName] = [];
}
acc[filterName] = [].concat(current.keywords.map(item => item.toLocaleLowerCase()));
return acc;
}, {});
return filtersObj;
}
期望的输出:
- 要在屏幕上呈现的所有过滤器的对象或数组
- 以过滤器名称作为键的对象,其值将是一个事件数组,其中包含与此过滤器关键字匹配的任何关键字
查看此代码示例:link
我的问题:
- 有没有更简单的方法来解决这个问题?
- 我将“filteredTimelineData”对象作为初始值传递给.reduce 函数。这是合法的吗?我在网上找不到这个问题的具体答案。
- 从时间复杂度的角度来看。如果数据集增长,此代码会导致任何内存问题吗?
【问题讨论】:
-
你想要的输出不是很清楚。
-
很抱歉。所需的输出是有一个对象,其过滤器名称作为键,值将是与此过滤器匹配的事件数组。
-
能否请您在问题中添加所需的输出,这样会更清楚。
-
做一个清晰的例子来说明过滤前后数据的样子。从你的例子来看,真的不清楚
-
添加了一个代码示例的链接。对不起,应该在开头添加的!
标签: javascript