javascript - 如何使用对象数组过滤数组对象
问题描述
我有一个像这样的过滤组js对象:
let filter = {
generalFilter:[
{key: "connected", value: true},
{key: "connected", value: false}
],
locationFilter:[
{key: "deviceLocation", value: "def"},
{key: "deviceLocation", value: "abc"}
],
paymentMethodsFilter:[
{key: "devicePaymentMethods", value: "ab"}
]
}
和这样的主数组:
const devices = [{
deviceLocation: {
label: "abc",
value: "abc"
},
deviceName: "test7",
devicePaymentMethods: [{
label: "ab",
value: "ab"
}, {
label: "cd",
value: "cd"
}, {
label: "ef",
value: "ef"
}],
deviceType: "iPad",
id: "001",
connected: true,
enabled: true,
},
{
deviceLocation: {
label: "def",
value: "def"
},
deviceName: "test4",
devicePaymentMethods: [{
label: "ab",
value: "ab"
}, {
label: "cd",
value: "cd"
}],
deviceType: "iPad",
id: "004",
connected: false,
enabled: false,
}
];
如何使用过滤器对象过滤此设备数组?这是我尝试过的,但它不起作用
devices.filter((device) => {
let shouldKeep = new Array(3)
shouldKeep.fill(0) //fills the array with 0, meaning no filter groups has passed yet
for(let filterGroupIndex in filter) {// Loop through each filter group in filter
let filterGroup = filter[filterGroupIndex]
for(let filterObject in filterGroup) { //Loop through
if(filterGroup[filterObject].key in device && device[filterGroup[filterObject].key] === filterGroup[filterObject].value) {
shouldKeep[filterGroupIndex] = 1 //Set current filterGroup to 1, meaning it has passed the filter
break; // At least one value in that filter group is true, skip to next filter group
}
}
}
if(shouldKeep.reduce((a,b) => a + b, 0) >= filter.length) {
return true;
}
return false
})
有时这个过滤器对象可能是空的,当它为空时它应该返回完整的数组而不过滤主数组。这样做的最佳方法是什么?我不确定这也许有另一种解决方案。请帮我
默认过滤器对象是这样的
let filter = {
generalFilter:[],
locationFilter:[],
paymentMethodsFilter:[]
}
例如,用户可以将对象添加到我正在使用反应挂钩的过滤器数组
let filter = {
generalFilter:[
{key: "connected", value: true},
{key: "connected", value: false}
],
locationFilter:[],
paymentMethodsFilter:[]}
然后我们必须检查两个 connected: false 和 connected: true 匹配主数组中的数据(如果数据已连接:主数组中的 true 则它会显示,如果数据已连接:false 它会显示)
对于这种类型的过滤器
let filter = {
generalFilter:[
{key: "connected", value: true},
{key: "connected", value: false}
],
locationFilter:[
{key: "deviceLocation", value: "def"},
{key: "deviceLocation", value: "abc"}
],
paymentMethodsFilter:[
{key: "devicePaymentMethods", value: "ab"}
]
}
结果应该是
result =[{
deviceLocation: {
label: "abc",
value: "abc"
},
deviceName: "test7",
devicePaymentMethods: [{
label: "ab",
value: "ab"
}, {
label: "cd",
value: "cd"
}, {
label: "ef",
value: "ef"
}],
deviceType: "iPad",
id: "001",
connected: true,
enabled: true,
},
{
deviceLocation: {
label: "def",
value: "def"
},
deviceName: "test4",
devicePaymentMethods: [{
label: "ab",
value: "ab"
}, {
label: "cd",
value: "cd"
}],
deviceType: "iPad",
id: "004",
connected: false,
enabled: false,
}
];
因为你可以在过滤器中看到 connected:true 和 connected :false 和 deviceLocation 与 def 和 abc 以及 devicePaymentMethods 是 ab
这意味着我希望所有连接 true 和连接 false 的设备与位置 abc 和 def 和 paymetmethod ab
解决方案
检查评论以获取解释。
const filter = {
generalFilter: [
{key: "connected", value: true},
{key: "connected", value: false}
],
locationFilter: [
{key: "deviceLocation", value: "def"},
{key: "deviceLocation", value: "abc"}
],
paymentMethodsFilter: [
{key: "devicePaymentMethods", value: "ab"}
]
};
const parsedFilter = {};
/**
converting filter into a hashmap with a filter as a Key and value as an
array of possible values.
parsedFilter looks like this
{"connected":[true,false],"deviceLocation":["def","abc"],"paymentOption":["ab"]}
now we can easily check if any value is present in the filter.
**/
const filterKeys = Object.keys(filter);
filterKeys.forEach((filterKey) => {
if (Array.isArray(filter[filterKey])) {
filter[filterKey].forEach((filterItem) => {
if (Object.prototype.hasOwnProperty.call(parsedFilter, filterItem.key)) {
parsedFilter[filterItem.key].push(filterItem.value);
} else {
parsedFilter[filterItem.key] = [filterItem.value];
}
});
}
});
const devices = [
{
deviceLocation: {
label: "abc",
value: "abc"
},
deviceName: "test7",
devicePaymentMethods: [
{
label: "ab",
value: "ab"
}, {
label: "cd",
value: "cd"
}, {
label: "ef",
value: "ef"
}],
deviceType: "iPad",
id: "001",
connected: true,
enabled: true,
}
];
const result = [];
/**
Looping through each device and check if that key is present in the
parsedFilter.
if true: check for typeof value for that device key.
if Object: then check if it is present in the array of not for the
givem deviceKey in parsedFilter.
if Array: then loop through each item and check if it is present
in the parsedFilter for the given deviceKey
if Number, string, boolean: Check if is present in the
parsedFilter for the given deviceKey
if false: simply add it to the result.
**/
if (Array.isArray(devices)) {
devices.forEach((device) => {
const keys = Object.keys(device);
const resultDeviceObj = {};
keys.forEach((key) => {
if (Object.prototype.hasOwnProperty.call(parsedFilter, key)) {
if (typeof device[key] === "object" && parsedFilter[key].includes(device[key].value)) {
resultDeviceObj[key] = device[key];
} else if (Array.isArray(device[key])) {
const arrayResult = [];
device[key].forEach((item) => {
if (parsedFilter[key].includes(item.value)) {
arrayResult.push(item);
}
});
resultDeviceObj[key] = arrayResult;
} else if(parsedFilter[key].includes(device[key])) {
resultDeviceObj[key] = device[key];
}
} else {
resultDeviceObj[key] = device[key];
}
});
result.push(resultDeviceObj);
});
}
console.log("result", result);
编辑
const filter = { generalFilter: [{key: "connected", value: true}], locationFilter: [{key: "deviceLocation", value: "abcd"}], paymentMethodsFilter: [{key: "devicePaymentMethods", value: "ab"}] }; const parsedFilter = {}; const filterKeys = Object.keys(filter); filterKeys.forEach((filterKey) => { if (Array.isArray(filter[filterKey])) { filter[filterKey].forEach((filterItem) => { if (Object.prototype.hasOwnProperty.call(parsedFilter, filterItem.key)) { parsedFilter[filterItem.key][filterItem.value] = filterItem.value; } else { parsedFilter[filterItem.key] = { [filterItem.value]: filterItem.value } } }); } }); //{"connected":{"true": true,"false": "false"},"deviceLocation":{"def": "def","abc": "abc"},"paymentOption":{"ab": "ab"}} const devices = [{ deviceLocation: { label: "abc", value: "abc" }, deviceName: "test7", devicePaymentMethods: [{ label: "ab", value: "ab" }, { label: "cd", value: "cd" }, { label: "ef", value: "ef" }], deviceType: "iPad", id: "001", connected: true, enabled: true, }, { deviceLocation: { label: "def", value: "def" }, deviceName: "test4", devicePaymentMethods: [{ label: "ab", value: "ab" }, { label: "cd", value: "cd" }], deviceType: "iPad", id: "004", connected: false, enabled: false, } ]; const result = []; const isObject = function (a) { return a.constructor.toString().indexOf("Object") !== -1; }; if (Array.isArray(devices)) { devices.forEach((device) => { const keys = Object.keys(device); let isValid = true; for (let i = 0; i < keys.length; i++) { const key = keys[i]; if (Object.prototype.hasOwnProperty.call(parsedFilter, key)) { if (isObject(device[key]) && !Object.prototype.hasOwnProperty.call(parsedFilter[key], device[key].value)) { isValid = false; break; } else if (Array.isArray(device[key])) { isValid = false; for (let j = 0; j < device[key].length; j++) { const item = device[key][j]; if (Object.prototype.hasOwnProperty.call(parsedFilter[key], item.value)) { isValid = true; break; } } if (!isValid) { break; } } else if (typeof device[key] === "boolean" && !Object.prototype.hasOwnProperty.call(parsedFilter[key], device[key])) { isValid = false; break; } } } if (isValid) { result.push(device); } } ); } console.log("result", result)
推荐阅读
- ios - 如何使用 socket.io 快速发送 ping?
- wpf - Segoe MDL2 Assets + 一键常规字体
- reactjs - TypeError:无法读取未定义的属性(读取“黑暗”)
- javascript - 根据 Schema 移除和添加属性
- sql-server - SQL Server:检查组中是否存在行
- r - 如何生成而不使用函数combn()在R中重复组合并概括代码?
- c - 调试开始时,将分解点放在变量上,该变量始终显示值为 1
- c++ - 如何在 C/C++ 中使用 OpenSSL 生成 DER 编码的公钥?
- xcode - Cocoapods Pod 包版本检查 - Flutter
- reactjs - React-Bootstrap Modals 导致窗口 EventListener 出现问题