How to combine my array and json result in one? - javascript

I want to combine two json results, but im struggling getting it done..
first one (galleryData):
[
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
]
second one (combinations):
{
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
}
the output im expecting:
{
data: [
{ round: 1, userId: 2, "profile": { "profileImage": "image" } },
{ round: 2, userId: 4, "profile": { "profileImage": "image" } }
]
}
Basically I need the profileImage from one of my result and map it to the correct user id
What I tried so far with no success:
let combinedResult = galleryData["userId"].map((item, i) => Object.assign({}, item, combinations[i]));

You can use map and on each callback use find to find the corresponding userId === partner
const galleryData = [
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
]
const combinations = {
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
}
let combinedResult = {
data: galleryData.map((item, i) => {
let combination = combinations.data.find(c => c.partner === item.userId);
return { ...item, round: combination.round }
})
};
console.log(combinedResult)

I think a little try using Array.forEach and then merge the Objects
a = [
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
]
b = {
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
}
// inside forEach you can write the logic to get elements from array 'a' as you can use `find` to check which user is needed
b.data.forEach((i,e) => { b.data[e] = {...i, ...a[e]} })
console.log(b)

Hope it will be helpful.
let galleryData = [
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
];
let galleryDataAsUserId = {};
galleryData.forEach(elem=>{
galleryDataAsUserId[elem.userId] = elem;
})
let combinations = {
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
};
let data = combinations.data;
data.map(elem=>{
let newElem = elem;
newElem.profile = galleryDataAsUserId[elem.partner].profile;
});
console.log(data)

Related

JavaScript - filter in loop, create duplicate

I want to filter an array with another array in order to know if there are new people.
const people = [
{ "name": "jerry" },
{ "name": "tom" },
{ "name": "alex" }
]
const newList = [
{ "name": "bran" },
{ "name": "jerry" },
{ "name": "john" }
]
const new_people = []
for (const pp of people) {
let result = newList.filter(newL => newL.name != pp.name)
if (result) {
new_people.push(result)
}
}
console.log(new_people)
This is the result:
[
[ { name: 'bran' }, { name: 'john' } ],
[ { name: 'bran' }, { name: 'jerry' }, { name: 'john' } ],
[ { name: 'bran' }, { name: 'jerry' }, { name: 'john' } ]
]
But I'm looking for:
[ { name: 'bran' }, { name: 'john' } ]
I would like to avoid the loop because it makes duplicate in the result but I don't know how I can't do it without the loop.
First make a temporary array of people name:
const peopleNames = people.map(pp => pp.name);
Then the peopleNames will be as follows:
['jerry', 'tom', 'alex']
Now filter the new people from the newList:
const newPeople = newList.filter(pp => !peopleNames.includes(pp.name));
The newPeople will be an array of objects that you are looking for.
[{name: 'bran'}, {name: 'john'}]
const people = [
{ "name": "jerry" },
{ "name": "tom" },
{ "name": "alex" }
]
const newList = [
{ "name": "bran" },
{ "name": "jerry" },
{ "name": "john" }
]
const output = newList.filter(a => people.filter(x => x.name == a.name).length == 0);
console.log('By USing Filter', output);
//filter the newList and retain those object, which are not present in the people
//Way 2: By using some
//const output2 = newList.filter(a => !people.some(x => x.name == a.name));
//console.log('By Using Some', output2);
You can use Array's reduce method to get the desired result:
const new_people = newList.reduce((accVal, e) =>
(people.map(p => p.name).includes(e.name))
? accVal
: accVal.concat({ "name": e.name } ),
[ ] )

String-path to Tree (JavaScript)

I have an array of paths in string format like that:
[
{ _id: 'women/clothes/tops', count: 10 },
{ _id: 'women/clothes/suits', count: 5 },
{ _id: 'women/accessories', count: 2 },
{ _id: 'men/clothes', count: 1 },
]
I would like to group them into a tree structure like that:
[
{
_id: 'women',
count: 17,
children: [
{
_id: 'clothes',
count: 15,
children: [
{ _id: 'tops', count: 10 },
{ _id: 'suits', count: 5 }
]
},
{
_id: 'accessories',
count: 2
}
]
},
{
_id: 'men',
count: 1,
children: [
{
_id: 'clothes',
count: 1
}
]
}
]
I would imagine a sort of recursive function calling a reduce method. But I can't figure how exactly.
EDIT :
I managed to get close with this solution. But I still get an empty object key, and i cannot manage to not have the children key when there are no children:
const getTree = (array) => {
return array.reduce((a, b) => {
const items = b._id.replace('\/', '').split('/')
return construct(a, b.count, items)
}, {})
}
const construct = (a, count, items) => {
const key = items.shift()
if(!a[key]) {
a[key] = {
_id: key,
count: count,
children: []
}
a[key].children = items.length > 0 ? construct(a[key].children, count, items) : null
}
else {
a[key].count += count
a[key].children = items.length > 0 ? construct(a[key].children, count, items) : null
}
return a
}
I created an object tree first and then converted that to your array of objects with children structure.
Note: I used a _count property on each object in the intermediate structure so that when looping over the keys later (when creating the final structure), I could ignore both _id and _count easily, and loop over only the "real children" keys, which don't start with _.
I did not look at your current attempt/solution before writing this, so mine looks quite different.
const origData = [
{ _id: 'women/clothes/tops', count: 10 },
{ _id: 'women/clothes/suits', count: 5 },
{ _id: 'women/accessories', count: 2 },
{ _id: 'men/clothes', count: 1 },
];
const newObj = {};
for (let obj of origData) {
//console.log(obj)
const tempArr = obj._id.split('/');
let tempHead = newObj; // pointer
for (let idx in tempArr) {
let head = tempArr[idx];
if (!tempHead.hasOwnProperty(head)) {
tempHead[head] = {};
}
tempHead = tempHead[head];
tempHead._id = head;
const currCount = tempHead._count || 0;
tempHead._count = currCount + obj.count;
}
tempHead._count = obj.count;
}
console.log(newObj);
const finalArr = [];
let tempArrHead = finalArr; // pointer
let tempObjHead = newObj; // pointer
function recursiveStuff(currObj, currArr, copyObj) {
let hasChildren = false;
const keys = Object.keys(currObj).filter(a => !a.startsWith("_"));
for (let key of keys) {
hasChildren = true;
const obj = {
_id: currObj[key]._id,
count: currObj[key]._count || 0,
children: [],
};
currArr.push(obj);
recursiveStuff(currObj[key], obj.children, obj)
}
if (hasChildren == false) {
// console.log(copyObj);
// there might be a more elegant way, but this works:
delete copyObj.children;
}
}
recursiveStuff(tempObjHead, tempArrHead)
console.log(finalArr);
.as-console-wrapper{
max-height: 100% !important;
}
Intermediate Structure:
{
"women": {
"_id": "women",
"_count": 17,
"clothes": {
"_id": "clothes",
"_count": 15,
"tops": {
"_id": "tops",
"_count": 10
},
"suits": {
"_id": "suits",
"_count": 5
}
},
"accessories": {
"_id": "accessories",
"_count": 2
}
},
"men": {
"_id": "men",
"_count": 1,
"clothes": {
"_id": "clothes",
"_count": 1
}
}
}
Final Structure:
[
{
"_id": "women",
"count": 17,
"children": [
{
"_id": "clothes",
"count": 15,
"children": [
{"_id": "tops", "count": 10},
{"_id": "suits", "count": 5}
]
},
{"_id": "accessories", "count": 2}
]
},
{
"_id": "men",
"count": 1,
"children": [
{"_id": "clothes", "count": 1}
]
}
]

Remove JSON attributes if not found in defined array

I need to remove attribute from the meta if it's not exist in att
for example : cardNo is not existing in the att
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
Expected output:
[
{
"id": 1,
"name": "test",
},
{
"id": 2,
"name": "test2"
}
];
for(let data of meta){
for (let key of Object.keys(data)) {
if (arr.indexOf(key) == -1) {
delete obj[key];
}
} }
Use Ramda.js (https://ramdajs.com/docs/) to make it easier:
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
]
const onlyAtts = map(pick(att), meta)
i think this is the answer for your question.
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
let newMeta = meta.map((d) => {
let obj = {};
att.forEach((currentAtt) => {
if(d.hasOwnProperty(currentAtt)) {
obj[currentAtt] = d[currentAtt];
}
});
return obj;
});
console.log(newMeta);
You can easily achieve this using map and reduce.
const att = ["id", "name", "class"];
const meta = [
{
id: 1,
name: "test",
cardNo: 23,
},
{
id: 2,
name: "test2",
cardNo: 232,
},
];
const result = meta.map((obj) => {
const perfectObj = att.reduce((acc, curr) => {
if (obj[curr]) {
acc[curr] = obj[curr];
}
return acc;
}, {});
return perfectObj;
});
console.log(result);
This is also works
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
function compare(meta, fields) {
meta.map(object => {
let dataKeys = Object.keys(object);
dataKeys.forEach(element => {
if(fields.indexOf(element) < 0) {
delete object[element];
}
});
});
}
compare(meta, att);
console.log(meta);

How to write Logic for given output?

I am trying to write a logic for given input and I need desired output in JavaScript.
Given Input:
var test = [{parentId:1,subId:1,subSubId:1},
{parentId:1,subId:2,subSubId:null},
{parentId:1,subId:null,subSubId:null},
{parentId:2,subId:1,subSubId:1},
{parentId:2,subId:null,subSubId:null}];
Expected output:
{
"category": [
{
"parentId": 1,
"subCatgory": [
{
"subId": 1,
"subSubCategory": [
{
"subSubId": 1
}
]
},
{
"subId": 2
}
]
},
{
"parentId": 2,
"subCatgory": [
{
"subId": 1
}
]
}
]
}
This code can perform that:
const test = [{
parentId: 1,
subId: 1,
subSubId: 1
},
{
parentId: 1,
subId: 2,
subSubId: null
},
{
parentId: 1,
subId: null,
subSubId: null
},
{
parentId: 2,
subId: 1,
subSubId: 1
},
{
parentId: 2,
subId: null,
subSubId: null
}
];
const parse = (data) => {
const category = data.reduce((acc, { parentId, subId, subSubId }) => {
let parent = acc.find(v => v.parentId === parentId)
if (!parent) {
parent = { parentId, subCategory: [] }
acc.push(parent)
}
if (!subId) return acc
let subCatetogy = parent.subCategory.find(v => v.subId === subId)
if (!subCatetogy) {
subCatetogy = { subId }
parent.subCategory.push(subCatetogy)
}
if (!subSubId) return acc
subCatetogy.subSubCategory = subCatetogy.subSubCategory || []
subCatetogy.subSubCategory.push({ subSubId })
return acc
}, [])
return { category }
}
console.log(parse(test))
Note: it seems like you've misspelled subCatgory so I've changed it to subCategory. And also parentId: 2 has subSubId: 1 in my solution, although it's in your test variable, but it seems missing in your desirable result.
Hope you find my answer useful :)
This code does what you need to do. It also works when subId and subSubId are both null. Please check:
const testData = [
{
parentId: 1,
subId: 1,
subSubId: 1
},
{
parentId: 1,
subId: 2,
subSubId: null
},
{
parentId: 1,
subId: null,
subSubId: null
},
{
parentId: 2,
subId: 1,
subSubId: 1
},
{
parentId: 2,
subId: null,
subSubId: null
},
{
parentId: 3,
subId: null,
subSubId: null,
}
];
function generateData(data) {
/**
* This will generate a map of objects that looks like this:
* map = {
* // parentId
* 1: {
* // subId
* 1: [
* // subSubId
* 1,
* 2,
* ...
* ],
* ...
* },
* ...
* }
*/
const map = data.reduce((result, { parentId, subId, subSubId }) => {
if (result[parentId]) {
if (!subId) return result;
if (result[parentId][subId]) {
if (!subSubId) return result;
result[parentId][subId].push(subSubId);
} else {
result[parentId][subId] = subSubId ? [subSubId] : [];
}
} else {
if (subId) {
result[parentId] = { [subId]: subSubId ? [subSubId] : [] };
} else {
result[parentId] = {};
}
}
return result;
}, {});
const categories = Object.keys(map).map(parentId => {
const parent = map[parentId];
const category = { parentId };
const subCategories = Object.keys(parent).map(subId => {
const subSubs = parent[subId];
const subCategory = { subId };
if (subSubs.length) {
subCategory.subSubCategory = subSubs.map(subSubId => ({ subSubId }));
}
return subCategory;
});
if (subCategories.length) {
category.subCategory = subCategories;
}
return category;
});
return { category: categories };
}
const result = generateData(testData);
console.log(result);
I added some comments so you can understand it easily, but it would take a bit of time to fully understand the logic.

Array Sort by time hh:mm:ss

I am trying to sort the time. but I am unable to sort by time (hh:mm:ss) format. so i have used moments js. my array sort by time not get sorted. how sort array by using maps
I have an array of objects:
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
let parsedDates = new Map(
elements.map(e =>[["id", "date"],[e.id, moment(e.date, 'hh:mm:ss')]])
);
elements.sort((a, b) => parsedDates.get(a) - parsedDates.get(b));
console.log(elements.map(e => ({ id: e.id, date: e.date })));
You can lexicographical sort the time using string.localeCompare().
let times = [ { "id": 1, "date": "02:01:02" }, { "id": 2, "date": "01:01:01" }, { "id": 3, "date": "03:01:01" }, { "id": 4, "date": "04:01:01" } ];
times.sort((a,b) => a.date.localeCompare(b.date));
console.log(times);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can try this
function convertDateObj(hhmmss){
let obj = new Date();//creates a Date Object using the clients current time
let [hours,minutes,seconds] = hhmmss.split(':');
obj.setHours(+hours); // set the hours, using implicit type coercion
obj.setMinutes(minutes); //you can pass Number or String, it doesn't really matter
obj.setSeconds(seconds);
return obj;
}
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
elements.sort((a, b) => convertDateObj(a.date) - convertDateObj(b.date)); // Ascending order
elements.sort((a, b) => convertDateObj(b.date) - convertDateObj(a.date)); // Descending order
The parsedDates map you've created is looking like:
Map {
[ 'id', 'date' ] => [ 1, <some Date object> ],
[ 'id', 'date' ] => [ 2, <some Date object> ],
[ 'id', 'date' ] => [ 3, <some Date object> ],
[ 'id', 'date' ] => [ 4, <some Date object> ]
}
And then you try to extract from it with elements like this:
parsedDates.get({ "id": 1, "date": "02:01:02" })
This should not work, because the key in a Map is and Array instance.
Even if you were using an array as a key:
parsedDates.get([ 1, "02:01:02" ])
this still wouldn't work, as this would be a different Object reference. I mean two arrays
a = [ 1, "02:01:02" ]
b = [ 1, "02:01:02" ]
are stored in different places and are different Objects, even though their values are identical.
So, you can modify your solution a bit:
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
let parsedDates = new Map(
elements.map(e => [e.date, e])
);
elements = elements.map(x => x.date).sort().map(x => parsedDates.get(x))
console.log(elements)
// [
// { id: 2, date: '01:01:01' },
// { id: 1, date: '02:01:02' },
// { id: 3, date: '03:01:01' },
// { id: 4, date: '04:01:01' }
// ]

Categories

Resources