I have an array that contains key and value like,
const array = [
{
DEVICE_SIZE: ['036', '048', '060', '070'],
},
{
DEVICE_VOLTAGE: ['1', '3'],
},
{
'NOT DEVICE_DISCHARGE_AIR': ['S'],
},
{
'NOT DEVICE_REFRIGERANT_CIRCUIT': ['H', 'C'],
},
];
The key here is going to play a major role for the result because of its NOT
keyword.
And I have original array of objects for each key like the following data,
const data = {
DEVICE_SIZE: [
{ id: 20, name: 'Size 20' },
{ id: 36, name: 'Size 36' },
{ id: 40, name: 'Size 40' },
{ id: 20, name: 'Size 48' },
{ id: 60, name: 'Size 60' },
{ id: 70, name: 'Size 70' },
],
DEVICE_VOLTAGE: [
{ id: 1, name: 'Voltage 1' },
{ id: 2, name: 'Voltage 2' },
{ id: 3, name: 'Voltage 3' },
{ id: 4, name: 'Voltage 4' },
{ id: 5, name: 'Voltage 5' },
],
DEVICE_DISCHARGE_AIR: [
{ id: 'E', name: 'Discharge E' },
{ id: 'S', name: 'Discharge S' },
{ id: 'T', name: 'Discharge T' },
],
DEVICE_REFRIGERANT_CIRCUIT: [
{ id: 'C', name: 'Refrigerant C' },
{ id: 'E', name: 'Refrigerant E' },
{ id: 'H', name: 'Refrigerant H' },
{ id: 'M', name: 'Refrigerant M' },
],
};
Requirement in detail:
Here for first two values DEVICE_SIZE
and DEVICE_VOLTAGE
it is positive case whereas for 'NOT DEVICE_DISCHARGE_AIR'
and 'NOT DEVICE_REFRIGERANT_CIRCUIT'
it has the keyword of NOT.
I need to filter all the above given array's and combine positive and negative result like,
Without NOT in the key:
For eg..,
DEVICE_SIZE: ['036', '048', '060', '070']
which is positive (without NOT keyword), so I need to get valid id's underDEVICE_SIZE
which isDEVICE_SIZE: [36, 48, 60, 70]
With NOT in the key:
For eg..,
'NOT DEVICE_DISCHARGE_AIR': ['S']
which is negative , so I need to get valid id's other than valueS
underDEVICE_DISCHARGE_AIR
which is["E", "T"]
If there is a NOT keyword in the object, then while mapping with the respective array of objects, I need to ignore the particular value and give other results.
Expected Output:
The final expected valid object would be,
const valid = {
DEVICE_SIZE: [36, 48, 60, 70],
DEVICE_VOLTAGE: [1, 3],
DEVICE_DISCHARGE: ["E", "T"],
DEVICE_REFRIGERANT_CIRCUIT: ["E", "M"],
};
CodePudding user response:
You could convert the array to a list of key/value pairs, flatten it, and then use a regex to extract the optional "NOT" prefix from it. Then you are left with a key in either case. With this key look up the corresponding IDs from the data array. If a "NOT" was found, filter those data IDs so those that are given in the array are excluded:
const filter = (data, filters) =>
Object.fromEntries(
filters.flatMap(Object.entries).map(([action, ids]) => {
let [, not, key] = action.match(/(NOT )?(.*)/);
let allids = data[key].map(({id}) => id);
if (typeof allids[0] == "number") ids = ids.map(Number);
if (not) {
ids = new Set(ids);
return [key, allids.filter(id => !ids.has(id))];
}
return [key, ids];
})
);
// Your example inputs:
const array = [{DEVICE_SIZE: ['036', '048', '060', '070'],},{DEVICE_VOLTAGE: ['1', '3'],},{'NOT DEVICE_DISCHARGE_AIR': ['S'],},{'NOT DEVICE_REFRIGERANT_CIRCUIT': ['H', 'C'],},];
const data = {DEVICE_SIZE: [{ id: 20, name: 'Size 20' },{ id: 36, name: 'Size 36' },{ id: 40, name: 'Size 40' },{ id: 20, name: 'Size 48' },{ id: 60, name: 'Size 60' },{ id: 70, name: 'Size 70' },],DEVICE_VOLTAGE: [{ id: 1, name: 'Voltage 1' },{ id: 2, name: 'Voltage 2' },{ id: 3, name: 'Voltage 3' },{ id: 4, name: 'Voltage 4' },{ id: 5, name: 'Voltage 5' },],DEVICE_DISCHARGE_AIR: [{ id: 'E', name: 'Discharge E' },{ id: 'S', name: 'Discharge S' },{ id: 'T', name: 'Discharge T' },],DEVICE_REFRIGERANT_CIRCUIT: [{ id: 'C', name: 'Refrigerant C' },{ id: 'E', name: 'Refrigerant E' },{ id: 'H', name: 'Refrigerant H' },{ id: 'M', name: 'Refrigerant M' },],};
const result = filter(data, array);
console.log(result);