I am trying to map an array with key like below
const data = [{
"_id": "5f0ffb96d67d70c1a3b143e7",
"name": "USER",
"type": "CUSTOM",
"origin": "USER",
"conditions": [{
"_id": "5f0ffb96d67d70c1a3b143e8",
"field": "status",
"value": "Nomita",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143e9",
"field": "current_status",
"value": "ACTIVE",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143ea",
"field": "user_group_uuid",
"value": "d12s0a7c-11ac-7abf-bl03-f0b70e26f8f2",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143eb",
"field": "user_group_uuid",
"value": "20348751-dcaa-4227-a0ff-912b27180aee",
"operator": "equal"
}]
}]
The above is the input.
const filters_data = { ...data[0] }
const filters_mapping = (array, keyField) =>
array.reduce((obj, item) => {
obj[item[keyField]] = item
return obj
}, {})
const filter_items = filters_mapping(filters_data.conditions,'field');
From this code I am getting
{ user_status:
{ _id: 5f0ffb96d67d70c1a3b143e8,
field: 'status',
value: 'Nomita',
operator: 'equal' },
current_status:
{ _id: 5f0ffb96d67d70c1a3b143e9,
field: 'current_status',
value: 'ACTIVE',
operator: 'equal' },
user_group_uuid:
{ _id: 5f0ffb96d67d70c1a3b143eb,
field: 'user_group_uuid',
value: 'd12s0a7c-11ac-7abf-bl03-f0b70e26f8f2',
operator: 'equal' } }
But I actually want something like this, that maps the value in array when the field is similar.
{ user_status:
{ _id: 5f0ffb96d67d70c1a3b143e8,
field: 'status',
value: 'Nomita',
operator: 'equal' },
current_status:
{ _id: 5f0ffb96d67d70c1a3b143e9,
field: 'current_status',
value: 'ACTIVE',
operator: 'equal' },
user_group_uuid:
{ _id: 5f0ffb96d67d70c1a3b143eb,
field: 'user_group_uuid',
value: ['d12s0a7c-11ac-7abf-bl03-f0b70e26f8f2','20348751-dcaa-4227-a0ff-912b27180aee'],
operator: 'equal' } }
this should happen only when there's multiple fields are available or else, it would return normal string only.
Ciao, I'm using your code but before reduce I combine value with same field value.
Here working example:
const data = [{
"_id": "5f0ffb96d67d70c1a3b143e7",
"name": "USER",
"type": "CUSTOM",
"origin": "USER",
"conditions": [{
"_id": "5f0ffb96d67d70c1a3b143e8",
"field": "status",
"value": "Nomita",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143e9",
"field": "current_status",
"value": "ACTIVE",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143ea",
"field": "user_group_uuid",
"value": "d12s0a7c-11ac-7abf-bl03-f0b70e26f8f2",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143eb",
"field": "user_group_uuid",
"value": "20348751-dcaa-4227-a0ff-912b27180aee",
"operator": "equal"
}]
}]
const conditions_combined = _.uniqWith(data[0].conditions, function(a, b) {
if (a.field === b.field) {
b.value += ', ' + a.value;
b.value = b.value.split(",");
return true;
}
});
data[0].conditions = conditions_combined;
const filters_data = { ...data[0] };
const filters_mapping = (array, keyField) =>
array.reduce((obj, item) => {
obj[item[keyField]] = item
return obj
}, {})
const filter_items = filters_mapping(filters_data.conditions,'field');
console.log(filter_items);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.10/lodash.min.js"></script>
Explanation: I'm using _.uniqWith from lodash to combine value with same field value.
Here is one possible soluce.
Your code doesn't handle the case where the key already exists.
const data = [{
"_id": "5f0ffb96d67d70c1a3b143e7",
"name": "USER",
"type": "CUSTOM",
"origin": "USER",
"conditions": [{
"_id": "5f0ffb96d67d70c1a3b143e8",
"field": "status",
"value": "Nomita",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143e9",
"field": "current_status",
"value": "ACTIVE",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143ea",
"field": "user_group_uuid",
"value": "d12s0a7c-11ac-7abf-bl03-f0b70e26f8f2",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143eb",
"field": "user_group_uuid",
"value": "20348751-dcaa-4227-a0ff-912b27180aee",
"operator": "equal"
}]
}];
const mutatedData = data[0].conditions.reduce((tmp, {
_id,
field,
value,
operator,
}) => {
// Handle the case where the field already exists
if (tmp[field]) {
tmp[field].value = [
...(tmp[field].value instanceof Array ?
tmp[field].value : [tmp[field].value]),
value,
];
return tmp;
}
// Handle the case where the field doesn't exist yet
tmp[field] = {
_id,
field,
value,
operator,
};
return tmp;
}, {});
console.log(mutatedData);
Condensed version
const data = [{
"_id": "5f0ffb96d67d70c1a3b143e7",
"name": "USER",
"type": "CUSTOM",
"origin": "USER",
"conditions": [{
"_id": "5f0ffb96d67d70c1a3b143e8",
"field": "status",
"value": "Nomita",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143e9",
"field": "current_status",
"value": "ACTIVE",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143ea",
"field": "user_group_uuid",
"value": "d12s0a7c-11ac-7abf-bl03-f0b70e26f8f2",
"operator": "equal"
}, {
"_id": "5f0ffb96d67d70c1a3b143eb",
"field": "user_group_uuid",
"value": "20348751-dcaa-4227-a0ff-912b27180aee",
"operator": "equal"
}]
}];
const mutatedData = data[0].conditions.reduce((tmp, {
_id,
field,
value,
operator,
}) => (tmp[field] = tmp[field] ? ((tmp[field].value = [
...(tmp[field].value instanceof Array ?
tmp[field].value : [tmp[field].value]),
value,
]) && tmp[field]) : {
_id,
field,
value,
operator,
}) && tmp, {});
console.log(mutatedData);
Related
Given the following objects stored in documents array:
[
{
"id": 61,
"created_at": "2022-11-02T15:36:25+00:00",
"updated_at": "2022-11-02T15:36:25+00:00",
"translations": [
{
"field": "name",
"lang": "it",
"text": "IT_Codice di Condotta_NEW"
},
{
"field": "name",
"lang": "en",
"text": "EN_Code of Conduct_NEW"
},
{
"field": "pdf_url",
"lang": "en",
"text": "/var/www/vhosts/marchettopellami.com/reservedarea.marchettopellami.com/docs/docs/en/a-20221125081444740491.pdf"
},
{
"field": "pdf_url",
"lang": "it",
"text": "/var/www/vhosts/marchettopellami.com/reservedarea.marchettopellami.com/docs/docs/it/draft-20221127194030220505.pdf"
}
]
},
{
"id": 63,
"created_at": "2022-11-02T15:38:40+00:00",
"updated_at": "2022-11-02T15:38:40+00:00",
"translations": [
{
"field": "name",
"lang": "it",
"text": "IT_NEW"
},
{
"field": "name",
"lang": "en",
"text": "EN_NEW"
},
{
"field": "pdf_url",
"lang": "en",
"text": "TheFerrari-GlobalMarketingStrategy-20221124133159490323.pdf"
},
{
"field": "pdf_url",
"lang": "it",
"text": "20221124160623761884.pdf"
}
]
},
]
My goal is to filter the value of "text" nested inside "translations" where "field" have value of "name". In other words filter IT_Codice di Condotta_NEW or EN_Code of Conduct_NEW for example
const resultsArray = documents.filter((d) => {
return Object.values(d)
.join(" ").toLowerCase()
.includes(e.target.value.toLowerCase())
});
At the moment the filter is working with "id", "created_at", "updated_at". I assume I should map translations array, but at the moment i can not even access "translations".
Thanks for your help.
You could expand those translation arrays by chaining the following after Object.values(d):
.flatMap(val => Array.isArray(val) ? val.map(({text}) => text) : val)
So it becomes:
const resultsArray = documents.filter((d) => {
return Object.values(d)
.flatMap(val => Array.isArray(val) ? val.map(({text}) => text) : val)
.join(" ").toLowerCase()
.includes(e.target.value.toLowerCase());
});
I am trying to change the value of object from the array but, it's not work as expected. I tried following.
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "another",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
},
]
arrObj.forEach(obj => {
obj = {...obj, ...obj.field}
delete obj.field
})
console.log("after:", arrObj);
Also I found some solution that to use index but, it add index before the object.
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "abcd",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
}
]
arrObj.forEach((obj, index) => {
obj[index] = {...obj, ...obj.field}
delete obj.field
})
console.log("after:", arrObj);
How can I do with forEach?
Edit:
I want to remove the field object and assign/overwrite all the property outside.
Using map and assigning the result is probably a better way of doing this, but if you want to use forEach, you need to assign to the original array inside the loop:
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "another",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
},
]
arrObj.forEach(({ field, ...rest}, idx, orig) => {
orig[idx] = { ...rest, ...field }
})
console.log(arrObj);
I would use map to change an array, but you may have a reason that you wish to modify the original. You could just reassign arrObj to the output of the map.
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "another",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
},
]
const newArr = arrObj.map(( obj ) => {
const {field, ...rest} = obj
return {...field, ...rest}
})
console.log("after:", newArr);
I have an array as under
Data =
[
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": []
}
]
},
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
}
]
}
]
Data array has two objects. I want to merge the aggregate property of second object in the first one.
something like this:
[
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
}
]
}
]
is there any way to implement this. Level of nesting is dynamic but all the objects will have same structure.
To merge the 2 objects inside the array into 1, this involves
Step 1. extracting the required elements from the 2nd object
Step 2. adding it into the object of the first.
Suppose the array is read into a variable data, then this is 1 way we can extract it in Step 1.
let {
aggregates: {
VALVAL_ALT_CMB_AMT
},
} = data[1];
The value paired to the VALVAL_ALT_CMB_AMT key of the 2nd object is stored inside a variable VALVAL_ALT_CMB_AMT. You can read more about Object Destructuring in Javascript.
For Step 2, we will add the value into the first variable. We can also think of objects to have similar syntax to maps, hence this is 1 way we can do it.
let first = data[0];
first["aggregates"]["VALVAL_ALT_CMB_AMT_1"] = VALVAL_ALT_CMB_AMT;
Extracting and adding the elements this way forms a shallow copy of the variable VALVAL_ALT_CMB_AMT, now as a value of VALVAL_ALT_CMB_AMT_1. Consequently, it is not advisable to delete the actual object in position 1 from the original array. Instead, it might be better to return the new object first in a new array.
const result = [first];
return result;
I have Object Like this
var RecuiterInfo = {}
RecruiterInfo.Quote: "1"
RecruiterInfo.CompanyName: "Imperial Innovations",
RecruiterInfo.OrganizationSize: "2",
RecruiterInfo.Person.CitizanZenship: null,
RecruiterInfo.Person.DOB: "Farkhonda#hotmail.com",
RecruiterInfo.Person.Email: "Farkhonda",
RecruiterInfo.Person.FirstName: "FaiZi",
RecruiterInfo.Person.Gender: "4456565656"
RecruiterInfo.Person.LastName: "4456565656",
RecruiterInfo.Person.PhoneNo: "4456565656",
RecruiterInfo.Person.UserId.UserName: "MTIzNDU2",
RecruiterInfo.Person.UserId.Password: null
I want to convert this object to
this specific format Like
{
"QueryObjectID":"RecruiterInfo",
"Values": [
{
"AppFieldID": "Person",
"Value": [
{
"AppFieldID": "CitizanZenship",
"Value": "1"
},
{
"AppFieldID": "DOB",
"Value": "01/01/2019"
},
{
"AppFieldID": "Email",
"Value": "test1#test.com"
},
{
"AppFieldID": "FirstName",
"Value": "test"
},
{
"AppFieldID": "Gender",
"Value": "1"
},
{
"AppFieldID": "LastName",
"Value": "test last"
},
{
"AppFieldID": "PhoneNo",
"Value": "7897897895"
},
{
"AppFieldID": "UserId",
"Value": [
{
"AppFieldID": "UserName",
"Value": "test1#test.com"
},
{
"AppFieldID": "Password",
"Value": "123456"
}
]
}
]
},
{
"AppFieldID": "Quote",
"Value": "Hi Im test"
},
{
"AppFieldID": "CompanyName",
"Value": "Terst"
}
]
}
but it should be a generic/dynamic(I don't want any static stuff here, because in feature there will be a multiple dot/ or nested objects)
I think loop will be based on .(dot),and it will be nested not sure
can any one help me for this json convert
Thanks in advance
You can do it recursively.
const convert = (obj) => {
if (obj === null) return null
if (typeof obj !== 'object') return obj
return Object.entries(obj)
.reduce((acc, [key, value]) => acc.concat({
AppFieldId: key,
Value: convert(value), // Recursive call
}), [])
}
console.log(JSON.stringify(convert(RecruiterInfo), null, 2))
It's not exactly like you want, but you'd need static stuff for that first bit.
[
{
"AppFieldId": "Quote",
"Value": "1"
},
{
"AppFieldId": "CompanyName",
"Value": "Imperial Innovations"
},
{
"AppFieldId": "OrganizationSize",
"Value": "2"
},
{
"AppFieldId": "Person",
"Value": [
{
"AppFieldId": "CitizanZenship",
"Value": null
},
{
"AppFieldId": "DOB",
"Value": "Farkhonda#hotmail.com"
},
{
"AppFieldId": "Email",
"Value": "Farkhonda"
},
{
"AppFieldId": "FirstName",
"Value": "FaiZi"
},
{
"AppFieldId": "Gender",
"Value": "4456565656"
},
{
"AppFieldId": "LastName",
"Value": "4456565656"
},
{
"AppFieldId": "PhoneNo",
"Value": "4456565656"
},
{
"AppFieldId": "UserId",
"Value": [
{
"AppFieldId": "UserName",
"Value": "MTIzNDU2"
},
{
"AppFieldId": "Password",
"Value": null
}
]
}
]
}
]
You could take an iterative approach.
var data = { 'RecruiterInfo.Quote': "1", 'RecruiterInfo.CompanyName': "Imperial Innovations", 'RecruiterInfo.OrganizationSize': "2", 'RecruiterInfo.Person.CitizanZenship': null, 'RecruiterInfo.Person.DOB': "Farkhonda#hotmail.com", 'RecruiterInfo.Person.Email': "Farkhonda", 'RecruiterInfo.Person.FirstName': "FaiZi", 'RecruiterInfo.Person.Gender': "4456565656", 'RecruiterInfo.Person.LastName': "4456565656", 'RecruiterInfo.Person.PhoneNo': "4456565656", 'RecruiterInfo.Person.UserId.UserName': "MTIzNDU2", 'RecruiterInfo.Person.UserId.Password': null },
result = Object.entries(data).reduce((r, [s, v]) => {
var path = s.split('.'),
last = path.pop();
path
.reduce((o, k, i) => {
var temp = o.find(q => q[i ? 'AppFieldID' : 'QueryObjectID'] === k);
if (!temp) o.push(temp = i ? { AppFieldID: k, Value: [] } : { QueryObjectID: k, Values: [] });
return temp[i ? 'Value' : 'Values'];
}, r)
.push({ AppFieldID: last, Value: v });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
{
"ID": "5c9b2de495e8d81ef437539e",
"WeightingFactor": "BIC",
"TargetAmount": 1000,
"FilterCondition": {
"_cls": "ComplexFilter",
"Condition": "AND",
"Rules": [{
"_cls": "Filter",
"Field": "MOODYSFOREIGNCURRENCYCEILINGRATING",
"Operator": "in list",
"Value": "A1,A2,A3"
},
{
"_cls": "Filter",
"Field": "ASOFDATE",
"Operator": "less or equal",
"Value": "26 Nov 2028"
},
{
"_cls": "ComplexFilter",
"Condition": "OR",
"Rules": [{
"_cls": "Filter",
"Field": "ASOFDATE",
"Operator": "less or equal",
"Value": "26 Nov 2028"
},
{
"_cls": "Filter",
"Field": "ASOFDATE",
"Operator": "less or equal",
"Value": "26 Nov 2029"
}
]
}
],
"Not": false
}
}
Need to rename "field" to category everywhere. Kindly suggest how is it possible using any available methods ?
Tried stringify and replace. But it's not working
Expected output :
{
"ID": "5c9b2de495e8d81ef437539e",
"WeightingFactor": "BIC",
"TargetAmount": 1000,
"FilterCondition": {
"_cls": "ComplexFilter",
"Condition": "AND",
"Rules": [{
"_cls": "Filter",
"Category": "MOODYSFOREIGNCURRENCYCEILINGRATING",
"Operator": "in list",
"Value": "A1,A2,A3"
},
{
"_cls": "Filter",
"Category": "ASOFDATE",
"Operator": "less or equal",
"Value": "26 Nov 2028"
},
{
"_cls": "ComplexFilter",
"Condition": "OR",
"Rules": [{
"_cls": "Filter",
"Category": "ASOFDATE",
"Operator": "less or equal",
"Value": "26 Nov 2028"
},
{
"_cls": "Filter",
"Category": "ASOFDATE",
"Operator": "less or equal",
"Value": "26 Nov 2029"
}
]
}
],
"Not": false
}
}
You could replace the strings "field": with "category": in the given JSON string.
var json = JSON.stringify({ field: { field: 'foo' } }),
newJSON = json.replace(/"field":/g, '"category":');
console.log(JSON.parse(newJSON));
A classical replacement
function replace(object, source, target) {
return Object.assign(...Object.entries(object).map(([k, v]) => ({
[k === source ? target : k]: v && typeof v === 'object'
? replace(v, source, target)
: v
})));
}
var object = { field: { field: 'foo' } },
newObject = replace(object, 'field', 'category');
console.log(newObject);
I ran a performance test on Regex replacing a key vs deep traversing a JSON object and replacing a key and it turns out the Regex way is 65% slower than the deep traversal approach.
Here is the code to do it the deep traversal way :
function deepTraverseAndReplace(o,sk,rk) {
for (var key in o) {
if (o[key ] !== null && typeof(o[key])=="object") {
traverse(o[key],sk,rk);
} else if( key == sk ) {
o[rk] = o[key];
delete(o[key]);
}
}
}
deepTraverseAndReplace(jsonObj,'Field','Category')
Here is the link of the create jsPerf