Merge Two Javascript Objects with Multiple Matches Per Key - javascript

I have two objects which I am trying to merge. I am almost successfully worked with answer from this question (Merge two unordered objects with different keys but same value?).
The issue is that in my "transpatterns" object, I have two patterns that match "Intercom" key. However, in my output, it only takes the second one. I need it to list both under the same key.
Here is my code:
var hash = {};
var partitions = [{
'$': {
uuid: '{0F314A21-B066-B597-BCFA-6EC88CF8813B}'
},
name: ['AllPhones']
},
{
'$': {
uuid: '{4DCF3A89-ADA1-2770-4154-F6E0204D9A71}'
},
name: ['Unity_Connection']
},
{
'$': {
uuid: '{B653BC00-2D90-790C-AE0D-16C3DD2F8EDD}'
},
name: ['LAB-Tansform-Calling']
},
{
'$': {
uuid: '{148C8971-87E4-49D3-1536-69B6C95293B3}'
},
name: ['Blocked']
},
{
'$': {
uuid: '{25534E0F-F69A-FDDB-2FAD-34312BB6CEFC}'
},
name: ['LAB-PSTN-Sim-911']
},
{
'$': {
uuid: '{EC1E144B-2C8C-22CC-F1F5-423CF0343367}'
},
name: ['LAB-PSTN-Sim-Local']
},
{
'$': {
uuid: '{9C7F3223-AE2D-7605-C642-0CEAB81CD555}'
},
name: ['LAB-PSTN-Sim-LD']
},
{
'$': {
uuid: '{15AFADC3-859B-2806-B9D1-5678CE035E3D}'
},
name: ['LAB-PSTN-Sim-Intl']
},
{
'$': {
uuid: '{5DD43CF0-5FB0-A6A0-A71D-D284265F37C7}'
},
name: ['Agents']
},
{
'$': {
uuid: '{7FDE7E11-F821-2491-BB08-E6A41DAB205D}'
},
name: ['UCCX']
},
{
'$': {
uuid: '{17500618-9567-92B9-8C15-95D794094A3F}'
},
name: ['Intercom']
},
{
'$': {
uuid: '{77049844-AB06-F899-26D0-C0940E20D4D5}'
},
name: ['Netech_Managers']
},
{
'$': {
uuid: '{A9DD47E0-1C4A-AAB9-E859-E6EEDB26E6B0}'
},
name: ['Assistant_Route_Point']
}
];
var transpatterns = [{
'$': {
uuid: '{3FF82ECB-7364-41DB-176B-65D28885339F}'
},
pattern: ['9.19005554444'],
description: ['Sample Outbound Call Block'],
routePartitionName: ['Blocked']
},
{
'$': {
uuid: '{18C2C829-AFAE-DB28-A003-5F1731907D85}'
},
pattern: ['555555XXXX'],
description: ['Inbound DID Range'],
routePartitionName: ['AllPhones']
},
{
'$': {
uuid: '{465EFEF8-C405-8D30-2C97-4BF9907C92C6}'
},
pattern: ['3100'],
description: ['Intercom Xlate'],
routePartitionName: ['Intercom']
},
{
'$': {
uuid: '{C17E117C-41C7-D459-8CD1-B1D3C4EDC40D}'
},
pattern: ['3101'],
description: ['Intercom Xlate'],
routePartitionName: ['Intercom']
}
];
// TESTING NEW
// COMBINE OBJECTS - CREATE HASH
function classify(e) {
if (hash[e.name] || hash[e.routePartitionName]) {
Object.keys(e).forEach(function (c) {
hash[e.name || e.routePartitionName][c] = e[c];
});
} else {
hash[e.routePartitionName || e.name] = e;
}
}
// COMBINE OBJECTS - ADD VARS to HASH
partitions.forEach(classify);
transpatterns.forEach(classify);
// COMBINE OBJECTS - ITERATE HASH + REMOVE ANY FIELDS
var combo = Object.keys(hash).map(function (e) {
delete hash[e]['routePartitionName'];
return hash[e];
});
console.log(combo);

I was able to solve my problem. I determined that I needed to collapse the object with multiple items associated with the same key before I merged the two objects. I was able to use the answer from this question to help me do this.
How to combine JSON object with same key and add their other corresponding values?
Here is the code I came up with that seems to work nicely.
// DEFINE VARIABLES
var partitions = [{
'$': {
uuid: '{0F314A21-B066-B597-BCFA-6EC88CF8813B}'
},
name: ['AllPhones']
},
{
'$': {
uuid: '{4DCF3A89-ADA1-2770-4154-F6E0204D9A71}'
},
name: ['Unity_Connection']
},
{
'$': {
uuid: '{B653BC00-2D90-790C-AE0D-16C3DD2F8EDD}'
},
name: ['LAB-Tansform-Calling']
},
{
'$': {
uuid: '{148C8971-87E4-49D3-1536-69B6C95293B3}'
},
name: ['Blocked']
},
{
'$': {
uuid: '{25534E0F-F69A-FDDB-2FAD-34312BB6CEFC}'
},
name: ['LAB-PSTN-Sim-911']
},
{
'$': {
uuid: '{EC1E144B-2C8C-22CC-F1F5-423CF0343367}'
},
name: ['LAB-PSTN-Sim-Local']
},
{
'$': {
uuid: '{9C7F3223-AE2D-7605-C642-0CEAB81CD555}'
},
name: ['LAB-PSTN-Sim-LD']
},
{
'$': {
uuid: '{15AFADC3-859B-2806-B9D1-5678CE035E3D}'
},
name: ['LAB-PSTN-Sim-Intl']
},
{
'$': {
uuid: '{5DD43CF0-5FB0-A6A0-A71D-D284265F37C7}'
},
name: ['Agents']
},
{
'$': {
uuid: '{7FDE7E11-F821-2491-BB08-E6A41DAB205D}'
},
name: ['UCCX']
},
{
'$': {
uuid: '{17500618-9567-92B9-8C15-95D794094A3F}'
},
name: ['Intercom']
},
{
'$': {
uuid: '{77049844-AB06-F899-26D0-C0940E20D4D5}'
},
name: ['Netech_Managers']
},
{
'$': {
uuid: '{A9DD47E0-1C4A-AAB9-E859-E6EEDB26E6B0}'
},
name: ['Assistant_Route_Point']
}
];
var transpatterns = [{
'$': {
uuid: '{3FF82ECB-7364-41DB-176B-65D28885339F}'
},
pattern: ['9.19005554444'],
description: ['Sample Outbound Call Block'],
routePartitionName: ['Blocked']
},
{
'$': {
uuid: '{18C2C829-AFAE-DB28-A003-5F1731907D85}'
},
pattern: ['555555XXXX'],
description: ['Inbound DID Range'],
routePartitionName: ['AllPhones']
},
{
'$': {
uuid: '{465EFEF8-C405-8D30-2C97-4BF9907C92C6}'
},
pattern: ['3100'],
description: ['Intercom Xlate'],
routePartitionName: ['Intercom']
},
{
'$': {
uuid: '{C17E117C-41C7-D459-8CD1-B1D3C4EDC40D}'
},
pattern: ['3101'],
description: ['Intercom Xlate'],
routePartitionName: ['Intercom']
}
];
var hash = {};
// FUNCTION - COMBINE ITEMS WITHIN OBJECT - WITH SAME KEY:routePartitionName
function combine(arr) {
var combined = arr.reduce(function (result, item) {
var current = result[item.routePartitionName];
result[item.routePartitionName] = !current ? item : {
pattern: current.pattern + ',' + item.pattern,
description: item.description,
routePartitionName: item.routePartitionName
};
return result;
}, {});
return Object.keys(combined).map(function (key) {
return combined[key];
});
}
// FUNCTION - COMBINE ITEMS WITHIN OBJECT - RUN
var result = combine(transpatterns);
// FUNCTION - COMBINE OBJECTS - CREATE HASH
function classify(e) {
if (hash[e.name] || hash[e.routePartitionName]) {
Object.keys(e).forEach(function (c) {
hash[e.name || e.routePartitionName][c] = e[c];
});
} else {
hash[e.routePartitionName || e.name] = e;
}
}
// FUNCTION - COMBINE OBJECTS - ADD VARS to HASH
partitions.forEach(classify);
result.forEach(classify);
// FUNCTION - COMBINE OBJECTS - ITERATE HASH + REMOVE ANY FIELDS
var combo = Object.keys(hash).map(function (e) {
delete hash[e]['routePartitionName'];
delete hash[e]['$'];
return hash[e];
});
console.log(combo);

Related

How do I group data that is nested in an array?

I have a array of objects and then inside each of the object I have another array, I want to group the data inside the object array according to their category name. I tried doing it with a reduce function but it is basically giving me the same data(it is not even transformed), It's like it is not even calling.
My Data
data = [
{
name: "listName",
id:434343,
data: [
{
id:434343,
categoryName: school,
},
{
id:234343,
categoryName: house,
},
{
id:2000,
categoryName: school,
},
{
id:2333,
categoryName: house,
}
]
},
{
name: "anotherListName",
id:434343,
data: [
{
id:434343,
categoryName: school,
},
{
id:234343,
categoryName: house,
},
{
id:2000,
categoryName: school,
},
{
id:2333,
categoryName: house,
}
]
}
]
my code
list.forEach(d =>
d.data.reduce((acc, currrent) => {
(acc[currrent.categoryName] = acc[currrent.categoryName] || []).push(
currrent
)
return acc
}, {})
)
How I want the data to be transformed
transformed = [
{
name: "listName",
id:43453,
data: {
school: [
{
id:434343,
categoryName:school
},
{
id:2000,
categoryName:school
},
],
house: [
{
id:234343,
categoryName:house
},
{
id:2333,
categoryName:house
},
],
}
},
{
name: "listName",
id:43453,
data: {
school: [
{
id:434343,
categoryName:school
},
{
id:2000,
categoryName:school
},
],
house: [
{
id:234343,
categoryName:house
},
{
id:2333,
categoryName:house
},
],
}
},
]
you can do something like this using map and reduce
const transform = data => data.map(({name, id, data}) => {
return {
name,
id,
data: data.reduce((res, {id, categoryName}) => {
return {
...res,
[categoryName]: [...(res[categoryName] || []), {id, categoryName }]
}
}, {})
}
})
const data = [{
name: "listName",
id: 434343,
data: [{
id: 434343,
categoryName: 'school',
},
{
id: 234343,
categoryName: 'house',
},
{
id: 2000,
categoryName: 'school',
},
{
id: 2333,
categoryName: 'house',
}
]
},
{
name: "anotherListName",
id: 434343,
data: [{
id: 434343,
categoryName: 'school',
},
{
id: 234343,
categoryName: 'house',
},
{
id: 2000,
categoryName: 'school',
},
{
id: 2333,
categoryName: 'house',
}
]
}
]
const result = transform(data)
console.log(result)

How to delete objects inside an object using an array? (React.js Reducer )

Example of the data (useContext)
data: {
projects:{
'project-1':{
name: 'project-1',
columnIds:['column-1', 'column-2'],
},
'project-2':{
name: 'project-2',
columnIds:['column-3'],
},
},
columns:{
'column-1':{
title: 'column-1',
content: 'abc',
},
'column-2':{
title: 'column-2',
content: 'def',
},
'column-3':{
title: 'column-3',
content: 'ghi',
},
},
}
If I delete the project-1 which has column-1 and column-2, it should also be deleted inside the columns object. So the result should be:
data: {
projects:{
'project-2':{
name: 'project-2',
columnIds:['column-3'],
},
},
columns:{
'column-3':{
title: 'column-3',
content: 'ghi',
},
},
}
I already know how to remove project-1 object but I'm stuck in removing the column-1 and column-2.
This was my code for removing column-1 and `column-2 data:
let newColumn = data.projects[projectname].columnIds.map((item) =>
Object.keys(data.columns).filter((key) => key !== item)
);
You just need to check if there are corresponding column IDs before you delete the property. If there are, iterate over the IDs and delete the columns:
const data = {
projects: {
'project-1': {
name: 'project-1',
columnIds: ['column-1', 'column-2'],
},
'project-2': {
name: 'project-2',
columnIds: ['column-3'],
},
},
columns: {
'column-1': {
title: 'column-1',
content: 'abc',
},
'column-2': {
title: 'column-2',
content: 'def',
},
'column-3': {
title: 'column-3',
content: 'ghi',
},
},
}
const key = 'project-1'
const { columnIds } = data.projects[key]
if (columnIds.length > 0) {
columnIds.forEach(id => {
delete data.columns[id]
})
}
delete data.projects[key]
console.log(data)
You can also create a copy of the object so you don't mutate the original one:
const data = {
projects: {
'project-1': {
name: 'project-1',
columnIds: ['column-1', 'column-2'],
},
'project-2': {
name: 'project-2',
columnIds: ['column-3'],
},
},
columns: {
'column-1': {
title: 'column-1',
content: 'abc',
},
'column-2': {
title: 'column-2',
content: 'def',
},
'column-3': {
title: 'column-3',
content: 'ghi',
},
},
}
function deleteColumns(obj, key) {
const copy = {
projects: { ...obj.projects },
columns: { ...obj.columns }
}
const { columnIds } = copy.projects[key]
if (columnIds.length > 0) {
columnIds.forEach(id => delete copy.columns[id])
}
delete copy.projects[key]
return copy
}
const afterDelete = deleteColumns(data, 'project-1')
console.log(afterDelete)
console.log(data)

How to compare objects using lodash regardless on their order

I am trying to compare two objects using lodash like below. The problem is that it always returns false. I think that the issue is that the objects have different order of keys and values. I however couldn't find a solution on how to compare it regardless on the order.
How to ignore the order and compare the two objects correctly?
var obj1 = {
event: 'pageInformation',
page: { type: 'event', category: 'sportsbook' },
username: 'anonymous',
pagePath: '/',
item: { name: 'Barcelona - Leganes', id: '123' },
contest: { name: '1.Španielsko', id: 'MSK70' },
category: { name: 'Futbal', id: 'MSK3' },
teams: [
{ id: 'barcelona', name: 'Barcelona' },
{ id: 'leganes', name: 'Leganes' }
]
}
var obj2 = {
event: 'pageInformation',
page: { type: 'event', category: 'sportsbook' },
username: 'anonymous',
pagePath: '/',
category: { id: 'MSK3', name: 'Futbal' },
contest: { name: '1.Španielsko', id: 'MSK70' },
item: { id: '123', name: 'Barcelona - Leganes' },
teams: [
{ name: 'Barcelona', id: 'barcelona' },
{ name: 'Leganes', id: 'leganes' }
]
}
function compareObjects(obj1, obj2){
return _.isMatch(obj1, obj2);
}
You can use the isEqual function which does a deep equal check (regardless of key order):
_.isEqual(obj1, obj2)
See more here: https://lodash.com/docs/2.4.2#isEqual

Collect flat array of deep nested data

I have dictionary:
var objectSchemasList = {
1: [
{
name: 'list_field1_1',
uuid: 'uuid1',
fieldObjectSchemaId: 2
},
{
name: 'list_field1_2',
uuid: 'uuid2',
fieldObjectSchemaId: null
},
],
2: [
{
name: 'list_field2_1',
uuid: 'uuid3',
fieldObjectSchemaId: null
},
{
name: 'list_field2_2',
uuid: 'uuid4',
fieldObjectSchemaId: null
},
],
3: [
{
name: 'list_field3_1',
uuid: 'uuid5',
fieldObjectSchemaId: 1
},
{
name: 'list_field3_2',
uuid: 'uuid6',
fieldObjectSchemaId: null
},
],
}
And array of related data to it:
const objectSchemaFields = [
{
name: 'field_1',
uuid: '_uuid1',
fieldObjectSchemaId: null
},
{
name: 'field_2',
uuid: '_uuid2',
fieldObjectSchemaId: null
},
{
name: 'field_3',
uuid: '_uuid3',
fieldObjectSchemaId: 1
},
];
It means that every object schema field can contain inside themselves other fields. That are linked by fieldObjectSchemaId. This mean that objectSchemaFields[2] element use objectSchemasList[objectSchemaFields[2].fieldObjectSchemaId]. That also uses objectSchemasList[2] and so on. It can be nested infinitely. I want to get flat array from this structure. Here i tried. Final array should be flat and has only path, name, uuid properties. Where path consists of concatenation of parent name and all nested child names splitted by point. For example result should be:
const result = [
{
path: 'field_1',
name: 'field_1',
uuid: '_uuid1',
},
{
path: 'field_2',
name: 'field_2',
uuid: '_uuid2',
},
{
path: 'field_3',
name: 'field_3',
uuid: '_uuid3',
},
{
path: 'field_3.list_field1_1',
name: 'list_field1_1',
uuid: 'uuid1',
},
{
path: 'field_3.list_field1_1.list_field2_1',
name: 'list_field2_1',
uuid: 'uuid3',
},
{
path: 'field_3.list_field1_1.list_field2_2',
name: 'list_field2_2',
uuid: 'uuid4',
},
{
path: 'field_3.list_field1_2',
name: 'list_field1_2',
uuid: 'uuid2',
}
]
It's not a good use case for map, because you still need to return the original object together with child objects, and you need to flatten it afterwards. Better stick with plain old array variable, or use reduce if you want to be fancy.
var output = [];
function processObject(path, obj) {
path = path.concat([obj.name]);
output.push({
path: path.join("."),
name: obj.name,
uuid: obj.uuid,
});
var schema = objectSchemasList[obj.fieldObjectSchemaId];
if (schema) {
schema.forEach(processObject.bind(null, path));
}
}
objectSchemaFields.forEach(processObject.bind(null, []));
https://jsfiddle.net/m8t54bv5/
You could reduce the arrays with a recursive call of a flattening function.
function flat(p) {
return function (r, { name, uuid, fieldObjectSchemaId }) {
var path = p + (p && '.') + name;
r.push({ path, name, uuid });
return (objectSchemasList[fieldObjectSchemaId] || []).reduce(flat(path), r);
};
}
var objectSchemasList = { 1: [{ name: 'list_field1_1', uuid: 'uuid1', fieldObjectSchemaId: 2 }, { name: 'list_field1_2', uuid: 'uuid2', fieldObjectSchemaId: null }], 2: [{ name: 'list_field2_1', uuid: 'uuid3', fieldObjectSchemaId: null }, { name: 'list_field2_2', uuid: 'uuid4', fieldObjectSchemaId: null }], 3: [{ name: 'list_field3_1', uuid: 'uuid5', fieldObjectSchemaId: 1 }, { name: 'list_field3_2', uuid: 'uuid6', fieldObjectSchemaId: null }] },
objectSchemaFields = [{ name: 'field_1', uuid: '_uuid1', fieldObjectSchemaId: null }, { name: 'field_2', uuid: '_uuid2', fieldObjectSchemaId: null }, { name: 'field_3', uuid: '_uuid3', fieldObjectSchemaId: 1 }],
result = objectSchemaFields.reduce(flat(''), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How can I select articles by categories in Meteor?

I'm a beginner meteor. I create a blog with many posts(article) by each categories. This is my Collection:
if (Category.find().count() === 0) {
[
{
name: 'IT',
sub_categories: [
{ name: 'Java' },
{ name: 'PHP' },
{ name: '.NET' },
{ name: 'Android/iOS' },
{ name: 'HTML/CSS' },
{ name: 'Javascript and Framworks' },
{ name: 'Ruby on Rails' },
],
},
{
name: 'ENGLISH',
sub_categories: [
{ name: 'Listening' },
{ name: 'Speaking' },
{ name: 'Writing' },
{ name: 'Reading' },
{ name: 'Topic' },
],
},
{
name: 'SoftSkill',
sub_categories: [
{ name: 'CV and CL' },
{ name: 'Presentation' },
{ name: 'Teamwork' },
],
},
{
name: 'ENTERTAINMENT',
sub_categories: [
{ name: 'Sports' },
{ name: 'Games' },
{ name: 'Music & Videos' },
{ name: 'Fashion' },
{ name: 'Talk show' },
],
},
].forEach(doc => {
Category.insert(doc);
});
}
After I save all posts by each categories, Now I want to show it throught select option
Details:
When I click on "IT" button -> app show all sub_categories. Then I choose one option (example "Java") it will show all posts have sub_categories = "Java". Can you help me to do it?
You can use navbar for your requirement.
In that navbar you can have dropdown as navbar element
Please Follow this steps if it is useful for you

Categories

Resources